Iniciando com Processing

Iniciando com Processing

Duas funções especiais precisam ser declaradas em um código de Processing para que ele funcione: a função setup() e a função draw(). A função setup() é responsável por configurar o documento / sketch, e estabelecer valores ou definições iniciais para as variáveis e funções. Já a função draw() é quem efetivamente realiza o trabalho de desenhar coisas na tela, sendo executada pela máquina computacional continuamente, na velocidade definida através de frameRate(), geralmente dentro de setup().

Todo código processing deve ter, no mínimo, estas duas funções declaradas. Elas fazem parte da estrutura mínima da programação em Processing. No exemplo abaixo, a função setup() configura um sketch de 150 x 150 pixels size(150,150), estabelece uma cor de fundo cinza clara background(#eeeeee), uma taxa de atualização de 20 quadros por segundo frameRate(20), cores laranjas para as bordas stroke(#F5871F) e preenchimento fill(#F5871F) do que for desenhado, e uma espessura de 2 pixels para as bordas ou linhas strokeWeight(2). Exceto pela a instrução size(), todas as demais definições poderiam ter sido feitas normalmente dentro de draw(), ao invés de setup() - mais precisamente, para cada elemento que for desenhado, convem definir todas as suas características no momento que o código responsável pelo desenho for colocado em draw().

Neste mesmo exemplo, a função draw() só realiza uma única tarefa: desenhar um quadrado com seu canto superior esquerdo nas posições 20 x 20 (pixels) do campo ortogonal presente no sketch, com dimensão de 110 x 110 pixels rect(20,20,110,110). É importante frisar que este retângulo está sendo repetidamente desenhado, um sobre o outro, em uma frequência de 20 vezes por segundo. Como não há nenhuma instrução para que o sketch seja apagado em cada vez que draw() é executada, o desenho sobrepõe o que já está lá. Experimente alterar as cores na função setup() ou modificar o que é desenhado para um círculo ou elípse, através da função ellipse(x,y,w,h).

void setup() {
  
  size(150,150);
  background(#40144D);
  frameRate(20);
  stroke(#78008A);
  strokeWeight(2);
  fill(#78008A);

}

void draw() {
  
  rect(20,20,110,110);

}

Utilizando as mesmas configurações de setup(), o exemplo abaixo desenha um pequeno círculo na posição em que o mouse se encontra sobre o sketch ellipse(mouseX, mouseY, 15, 15). Novamente, como nenhuma instrução é dada para que a tela seja limpa, o circulo vai deixando um rastro por onde o mouse passar. Experimente incluir uma instrução para que a tela seja limpa antes que o circulo seja desenhado, através da instrução background().

void draw() {
  
  ellipse(mouseX, mouseY, 15, 15);

}

Escopo

Escopo

Você pode declarar novas funções ou novas variáveis ao longo do código na medida que precisar. No exemplo abaixo, declaramos a função rastro() que faz a mesma coisa que o exemplo anterior: desenha um circulo na posição do mouse. Mas rastro() não é uma função executada automaticamente pela máquina computacional; as únicas funções que são executadas automaticamente são setup() uma única vez, e draw() continuamente. Se rastro() fosse chamada à partir de setup(), teríamos apenas um círculo, provavelmente na posição 0 x 0 do campo ortogonal, desenhado imediatamente no momento que o processamento do código é iniciado. Mas quando rastro() é chamada à partir de draw(), ela passa a ser executada toda vez que draw() é executada. Experimente cortar a chamada à rastro() dentro de draw(), e o código não desenhará mais nada na tela.

Para que rastro() esteja acessível para ser chamada por outras funções no código, ela precisa ser declarada no mesmo nível hierárquico das demais funções. Funções não podem ser declaradas dentro de funções (ou variáveis dentro de variáveis); declarar uma função dentro de outra função resultará em um erro de código. Mas variáveis podem ser declaradas dentro de funções. Classes / objetos são um terceiro elemento de programação - que serão vistos posteriormente - que podem ter diversas funções e variáveis declaradas dentro deles.

As funções declaradas dentro de classes/objetos só são acessíveis aos próprios objetos, e não podem ser usadas em outros lugares, como em draw() ou setup(), assim como uma variável declarada dentro de uma função não é acessível/visível para outra função. Isso é chamado, em programação, de escopo de variáveis e funções.

Se a variável cor int cor = #469CA2 tivesse sido declarada dentro de rastro(), draw() não saberia de sua existência, e o código pararia de funcionar em decorrência de um erro (uma variável que não existe por estar fora do escopo da função sendo utilizada nas chamadas a fill(cor) e stroke(cor) ). Contudo, se a variável cor int cor = #469CA2 for declarada dentro de rastro(), e as funções fill(cor) e stroke(cor) também forem colocadas dentro de rastro(), o código funcionará perfeitamente, já que a variável cor está sendo usada em um lugar onde ela faz parte do escopo. Experimente alterar o lugar das funções e da declaração da variável, para entender como isso funciona:

int cor = #36787e;

void draw() {
  fill(cor);
  stroke(cor);
  rastro();
}

void rastro() {
  ellipse(mouseX, mouseY, 15, 15);
}

Case sensitive

Case sensitive

Toda linguagem de programação que compartilha da sintaxe de Java faz diferenciação entre letras maísculas e letras minúsculas no código. Uma variável ou função declarada com todas as letras maísculas, ou com apenas a primeira letra maíscula, é diferente de outra com todas as letras minúsculas, ainda que as letras em si sejam as mesmas. Um dos erros mais comuns em códigos case sensitive são a digitação de variáveis e funções de formas diferentes quanto à maísculas e minúsculas. No exemplo abaixo declaramos duas variáveis com a mesma palavra, mas escritas de formas diferentes em relação às maísculas e minúsculas. Repare que a máquina computacional às interpreta como coisas completamente diferentes. Experimente trocar as variáveis utilizadas em fill() e stroke() para notar a diferença.

int cor = #78008A;
int Cor = #36787e;

void draw() {
  fill(Cor);
  stroke(cor);
  ellipse(mouseX, mouseY, 15, 15);
}

Comentários

Comentários

Toda linguagem de programação possui uma forma de incluir textos livres dentro do código, geralmente para explicações, anotações, comentários, ou meramente para documentar o que é aquele código. Os Comentários são ignorados pela máquina computacional, mas permanecem ali para o programador, ou para outros programadores que venham a ter contato com o código. É necessário usar uma sintaxe específica para que a máquina computacional entenda que o trecho deve ser ignorado. Há duas formas de se fazer isso, através de comentários por linha, e comentários multilinha. No primeiro caso, deve-se utilizar // no início do comentário; tudo que vier depois, naquela linha, será ignorado. No segundo caso, deve-se utilizar /* no início daquilo que é um comentário, e */ para determinar o que é o final do comentário.

Experimente modificar a posição das marcações ou fazer comentários no código abaixo:

void draw() {

  fill(#36787e); // cor azul

  /*
  fill(#78008A);
  */
 
  // a borda está azul
  stroke(#36787e);

  // background(#40144D);

  /* este trecho desenha
  os círculos.
  */
  ellipse(mouseX, mouseY, 15, 15);
}

Um código bem documentado, com comentários explicando cada decisão do programador, o funcionamento das funções, o esquema lógico do seu processamento, etc., é essencial para um bom desenvolvimento. O funcionamento de um código pode parecer óbvio quando se está trabalhando nele, mas podo ficar indecifrável após alguns meses sem vê-lo; por isso, é essencial que ele seja devidamente explicado nos comentários.

Console

Console

Para saber o que está acontecendo no seu código, entender o valor de alguma variável, ou acompanhar sua mudança, geralmente é necessário visualizar algum tipo de dado. Para fazer isso utilizamos o Console, um painel de texto disponível na IDE do Processing onde mensagens enviadas pelo código podem ser exibidas enquanto o programa é executado.

Para exibir mensagens no Console usamos as funções print(mensagem) e println(mensagem). Esta mensagem pode ser composta com o valor de variávies, textos, ou qualquer informação que o desenvolvedor julgar necessária visualizar. Enquanto print() exibe uma mensagem e mantem o cursor ao final desta mensagem, println() exibe a mensagem e pula a linha automaticamente.