Introdução ao Processing

Já houve um post sobre Processing há um tempo atrás, mas agora que me aprofundei um pouco, vou continuar o assunto …

Como foi dito, Processing é uma linguagem de programação destinada a designers e ilustradores. Foi criada no MIT, e é na verdade um subset da linguagem Java, mas com algumas facilidades destinadas a produção de peças gráficas, animações, interações etc. Esse fim de semana eu dei um pulo no MAM, onde estava acontecendo o Festival CulturaDigitalBR, e no sábado de manhã, uma oficina rápida de introdução ao Processing.

A onda do Processing é que é uma linguagem muito fácil de aprender. Mesmo se você nunca teve experiência prévia com programação, algumas linhas de código e um pouco de raciocínio podem produzir resultados incríveis. E essa sempre foi a ideia principal, desde quando John Maeda e seus estudantes do MIT Media Lab conceberam o projeto em 2001.

Vou compartilhar um pouco dessa descoberta inicial, pra você ver se você também se interessa na linguagem, e quem sabe corre atrás de mais informação. Eu digo descoberta inicial, pois isso é o básico do básico mesmo, pra quem nunca escreveu uma linha de código ver como o Processing serve pra qualquer ser pensante.

Começando

Pra início de conversa, você tem que baixar o aplicativo do Processing. Ele é gratuito e está disponível pra download em http://processing.org. Tem versões pra Windows, Mac e Linux. Instale-o e abra.

Essa é a janela principal do Processing. Não é nada mais do que um bloco de notas, onde você escreve o seu código. Lá em cima só tem os botões de play/stop pra rodar e parar o seu script, e botões de criar um novo, salvar, abrir e exportar como applet.

Pra testar isso, clique no Play (ou aperte Ctrl+R), e o Processing já abre uma janelinha 100 x 100 pixels, com um fundo cinza. É uma das coisas que ele faz pra você, sem você ter escrito nada. Ótimo, mas queremos ter controle sobre isso. Digite então:

size(510, 510);
background(#CCCCCC);

Essa função size é o que define o tamanho da janela. Se você não definir isso, é como se tivesse escrito size(100, 100);, pois esses são os valores padrão de size. No caso, eu defini que a tela vai ter 510 x 510 pixels.

A função background é o que define a cor do fundo. No caso eu coloquei um cinza em código hexadecimal, mas ele também aceita valores de vermelho, verde e azul (RGB) separados por vírgulas. Branco seria background(255, 255, 255). Um valor único de 0 a 255 também é um jeito rápido de definir tons de cinza, sendo 0 preto e 255 branco. Aperte o Play pra ver se funcionou.

A próxima coisa que podemos fazer é desenhar formas básicas na tela…

size(510, 510);
background(#CCCCCC);
ellipse(200, 100, 120, 60);
rect(200, 200, 80, 80);
line(100, 300, 400, 400);

O Processing tem muitas funções que criam formas geométricas, como ellipse (elipse), rect (retângulo) e line (linha). Cada um tem sua sintaxe de entrada de dados que dizem como eles vão ser desenhados. Esses dados são os números entre parênteses.

No caso da elipse, temos que informar primeiro onde ela vai ser desenhada, e depois o seu tamanho. Então a sintaxe traduzida é ellipse([coordenada x],[coordenada y], [largura], [altura]). O mesmo serve pra desenhar o retângulo. As coordenadas da tela consideram o canto superior esquerdo como o ponto (0,0), e a unidade de tudo isso é pixels.

Uma linha é basicamente a união entre dois pontos. Então pra desenhar uma, basta informar as coordenadas x e y desses dois pontos. No caso, a linha que desenhamos vai do ponto (100, 300) ao ponto (400, 400).

Até agora não vimos nada de super emocionante, especialmente com essas formas básicas, com preenchimento branco e contorno preto, todo serrilhado. Seria melhor continuar usando o Paint pra fazer isso.

Pra melhorar a aparência serrilhada, e introduzir um anti-alias, basta escrever smooth() lá em cima:

smooth();
size(510, 510);
background(#CCCCCC);
ellipse(200, 100, 120, 60);
rect(200, 200, 80, 80);
line(100, 300, 400, 400);

Melhor ! Mas queremos mudar a cor do preenchimento e do contorno…

smooth();
size(510, 510);
background(#CCCCCC);
noFill();
stroke(0, 0, 255);
ellipse(200, 100, 120, 60);
noStroke();
fill(255, 0, 0);
rect(200, 200, 80, 80);
stroke(60, 150, 60);
strokeWeight(3);
line(100, 300, 400, 400);

O que fizemos aqui foi definir, pra cada forma criada, características de preenchimento e contorno. O compilador lê o código de cima pra baixo, e do jeito que está, termina o programa no final. Então isso é praticamente uma lista de instruções que estamos dando pra ele. Repare que no final de cada instrução, temos que incluir um ponto e vírgula.

Primeiro instruímos como vai ser o tamanho e a cor da tela. Depois dizemos que a próxima forma que ele desenhar não vai ter nenhum preenchimento (noFill()) e um contorno azul (stroke(0, 0, 255)). Aí ele desenha a elipse desse jeito, nas coordenadas e no tamanho definidos.

Depois dizemos que a forma seguinte não vai ter contorno (noStroke()), e o preenchimento vai ser vermelho (fill(255, 0, 0)). E aí ele desenha o retângulo com essas propriedades, e as coordenadas e tamanho também informados.

Por último, dizemos que o contorno vai ser um verde (stroke(60, 150, 60)), com 3 pixels de espessura (strokeWeight(3)). E aí ele faz a linha com essas propriedades, nas coordenadas informadas.

Desenhando

Até agora não fizemos nada que o Paint não faça, então vamos continuar, e começar a ver como podemos usar essas formas pra criar ferramentas de desenho, e justificar mais o uso do programa.

Pra simplificar, vou trabalhar só com uma elipse mesmo:

smooth();
size(510, 510);
background(#333333);
noFill();
stroke(#FFFFFF);
ellipse(255,255,100,100

Repare que eu posicionei a elipse no centro da tela. Pra eu não ter que calcular o centro, posso aproveitar as variáveis width (largura) e height (altura), pra se caso eu queira mudar o tamanho da tela, não tenho que voltar e recalcular a posição da elipse:

smooth();
size(510, 510);
background(#333333);
noFill();
stroke(#FFFFFF);
ellipse(width/2,height/2,100,100);

Isso já mostra como o Processing já oferece variáveis prontas pra serem usadas, economizando o tempo de termos que criar variáveis muito usadas.

Até agora, tudo que escrevemos foi uma lista de instruções pro compilador, em que ele lê linha por linha, e no final termina o programa. Mas pra haver qualquer tipo de mudança visual ao longo do tempo, precisamos de algum tipo de bloco de código que seja repetido a cada frame. Pra isso introduzimos duas funções essenciais, próprias do Processing: setup() e draw().

Basicamente, a função setup() é rodada uma vez só, e é usada pra declarações iniciais como tamanho da tela, fundo etc. A função draw() é rodada em loop, uma vez a cada frame. O nosso código fica assim:

void setup() {
  smooth();
  size(510, 510);
  background(#333333);
  noFill();
  stroke(#FFFFFF);
}

void draw() {
  ellipse(width/2, height/2, 100, 100);
}

Com isso, podemos fazer algum valor dentro de draw() variar a cada quadro. Isso pode ser a posição da elipse. Ela pode assumir a posição do cursor:

void setup() {
  smooth();
  size(510, 510);
  background(#333333);
  noFill();
  stroke(#FFFFFF);
}

void draw() {
  ellipse(mouseX, mouseY, 100, 100);
}

Interessante …… Que tal fazer isso só quando o botão do mouse está pressionado ? Podemos usar uma condicional (if) e a variável do sistema mousePressed, pra dizer quando essas elipses vão ser desenhadas…

void setup() {
  smooth();
  size(510, 510);
  background(#333333);
  noFill();
  stroke(#FFFFFF);
}

void draw() {
  if (mousePressed){
    ellipse(mouseX, mouseY, 100, 100);
  }
}

Isso traduz como: a cada frame, se o botão do mouse estiver pressionado, desenhe uma elipse na posição do cursor, com 100 pixels de largura e 100 pixels de altura.

Podemos também fazer com que o tamanho e a cor do contorno das elipses desenhadas varie aleatoriamente, e de acordo com a posição do cursor. Pra isso, temos que jogar a função stroke pra dentro do draw, pra que ele mude a cada frame. Introduzimos também a função random, pra sortear valores aleatórios pro tamanho das elipses. Assim:

void setup() {
  smooth();
  size(510, 510);
  background(#333333);
  noFill();
}

void draw() {
  if (mousePressed) {
    stroke(mouseX/2);
    ellipse(mouseX, mouseY, random(20,80), random(20,80));
  }
}

Aqui, o valor de stroke é um cálculo, pra respeitar os valores aceitos pra cor (0 a 255). Se o cursor estiver na extrema direita da tela, esse valor vai ser dividido por 2, e retornar 255 como a cor do contorno da elipse.

Já o tamanho da elipse é definido por valores aleatórios (random), entre 20 e 80, tanto pra largura quanto pra altura. Então a cada frame esses valores variáveis são recalculados, e uma nova elipse é desenhada na tela.

12 linhas de código e alguns rabiscos depois …

Faz isso no Paint que eu quero ver, nenêm !

Animando

Todas essas funções e variáveis como stroke(), ellipse(), mousePressed, mouseX, etc são próprias do Processing, e são o que tornam a linguagem pronta pra ser usada por quem trabalha com estruturas visuais. Repare que quando elas são escritas, o editor marca essas palavras em azul, pra dizer que são palavras reservadas ao sistema. Mas muitas vezes, queremos definir as nossas próprias variáveis. Vou exemplificar com um cenário de um círculo animado:

void setup() {
  smooth();
  size(510, 510);
  background(#333333);
  noFill();
  stroke(#FFFFFF);
}

void draw() {
  ellipse(width/2, height/2, 30, 30);
}

Eu quero que essa elipse ande 1 pixel pra direita a cada quadro. Pra isso, a posição x da elipse vai ser incrementada em 1 pixel a cada quadro. Precisamos de uma variável pra isso.

Pense em uma variável como uma gaveta que armazena um dado qualquer. O que está dentro da gaveta pode ser consultado e alterado. No caso, queremos uma gaveta que guarde um valor numérico, que a cada quadro vai ser incrementado uma unidade, e consultado pelo campo da posição x da elipse.

float posX;

void setup() {
  smooth();
  size(510, 510);
  background(#333333);
  noFill();
  stroke(#FFFFFF);
  posX = width/2;
}

void draw() {
  ellipse(posX, height/2, 30, 30);
  posX = posX + 1;
}

Aqui, criamos a variável posX, que vai armazenar o valor variável da posição x da elipse.

Pra começar, temos que declarar a variável, ou seja, dizer o tipo de dado que ela vai conter, e o seu nome. Float é um tipo de dado próprio do sistema, e significa valores numéricos flutuantes (números inteiros e decimais). Outros tipos de dados do Processing podem ser int (números inteiros), boolean (verdadeiro/falso), String (sequência de caracteres alfanuméricos, representados entre aspas, como nomes e frases) etc. No caso, como a posição x do círculo poderá ser um número inteiro ou decimal, vamos usar float mesmo.

Segundo, é bom definir um valor inicial dessa variável. Isso é feito dentro do setup(), que é rodado uma vez na inicialização do programa.

Depois, dizemos que o valor da posição x da elipse vai ser o mesmo valor contido na variável posX. Isso é feito dentro do draw(), que roda em loop, uma vez a cada quadro.

Por último, incrementamos o valor de posX em uma unidade.

Beleza, mas eu não quero deixar esse rastro de círculos a cada quadro processado. Basta redefinir a cor do background, dentro do draw(). Assim, a cada quadro, o programa pinta o fundo por cima de tudo e desenha o círculo na sua nova posição:

float posX;

void setup() {
  smooth();
  size(510, 510);
  background(#333333);
  noFill();
  stroke(#FFFFFF);
  posX = width/2;
}

void draw() {
  background(#333333);
  ellipse(posX, height/2, 30, 30);
  posX = posX + 1;
}

Agora, entendido como funcionam as variáveis, podemos incrementar um pouco mais esse programa. Vamos fazer com que a posição x do cursor defina a velocidade do círculo. Ao mesmo tempo, vamos fazer com que o círculo volte pro início da tela, se ele sair de vista:

float posX;
float velX;

void setup() {
  smooth();
  size(510, 510);
  background(#333333);
  noFill();
  stroke(#FFFFFF);
  posX = width/2;
}

void draw() {
  background(#333333);
  velX = mouseX/10;
  ellipse(posX, height/2, 30, 30);
  if (posX > width) {
    posX = 0;
  } 
  else {
    posX = posX + velX;
  }
}

Aqui, introduzimos mais uma variável, velX, e definimos que ela vai ser a posição x do cursor dividido por 10 (pra limitar o incremento da posição x da elipse em até 51px por quadro).

Introduzimos uma condicional que vai cuidar do valor de posX assim: Se a elipse estiver em uma posição x maior do que a largura da tela, coloque-a de volta na esquerda da tela. Se não (else), incremente a posição x no valor que estiver na variável velX (definida pela posição x do cursor dividido por 10).

Veja como ficou isso aqui.

————————–

Isso tudo é só pra riscar a superfícia, e não gera muito resultado útil por si só. Mas entendendo a lógica de funcionamento de programas como o Processing, conseguimos ir descobrindo novas possibilidades através da experimentação que empurra o estudo. É importante se desafiar a cada etapa, e com isso ir aprendendo novas técnicas. Mesmo se não tiver aplicação prática, entender e exercitar os conceitos de variáveis, funções, propriedades, métodos, classes, etc é crucial pra mergulhar em qualquer linguagem de programação, e o Processing é uma ótima porta de entrada pra quem se interessa em produzir suas próprias ferramentas visuais, e aproveitar o poder de processamento do computador.

O computador se tornou a ferramenta padrão de hoje em dia, mas muitas vezes esquecemos da sua capacidade de processar imensas quantidades de informação e executar cálculos complicadíssimos em frações de segundo. Isso pode ser aproveitado pra criar ferramentas únicas e peças gráficas complexas e sofisticadas, se soubermos falar a língua da máquina.

Pra estender o assunto, o próprio site do Processing é uma ótima referência, com o dicionário da sintaxe, bibliotecas e ferramentas pra criar qualquer coisa, seja pra web, instalações interativas, animações, etc. Comece por lá.

Agradecimento especial ao prof. Tande, da Kabum BH que veio ao RJ despertar o meu interesse pelo Processing.

9 comentários para “Introdução ao Processing”

  1. Douglas

    Muito bom o post =) conhecia um pouco de processing já, pelo site deles (processing.org) que tem uma biblioteca com todas as funções e tal. estou tentando aprender um pouco de nodebox também, que é parecido mas baseado em Python ao invés de Java =)

    Responder
    • João Faraco

      Boa ! Não conhecia o Nodebox, mas conheço gente que faz programas bem simples e úteis com Python. Dizem que também é uma boa linguagem pra quem quer começar a mexer com programação. Eu gostei do Processing por causa do retorno visual imediato que ele dá. Imagino que o Nodebox seja a mesma coisa.

      Responder
  2. Raphael Fuzari

    O processing é bem legal mesmo. Estudo Design de Interfaces Digitais no Centro Universitário Senac. Nesse fim de semestre produzimos um protótipo de cama, onde as funções de um despertador foram adicionadas a ela. Além disso, adicionamos algumas outras funções como vibração e luzes que servem de auxilio para acordar a pessoa. Todas as funções foram programadas em processing, foi bem divertido participar desse projeto.

    Responder

Deixe um comentário construtivo

XHTML: Você pode usar as seguintes tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>