Aula 04 – Estrutura condicional e criação de variáveis
Objetivo
Até agora o código que escrevemos caracterizou-se por ser executado linha a linha e do início ao fim do programa. A única alteração de fluxo trabalhada foi implementada através do bloco draw, que permite que seja feita a repetição de parte do código indefinidamente. Entretanto, em um programa de computador muitas vezes torna-se necessário um controle mais fino do fluxo de execução. Por exemplo, realizar um desenho apenas quando uma certa condição esteja satisfeita. Para este controle será necessária a definição da estrutura condicional, representada pela palavra chave if.
Este capítulo trata desta estrutura, mas também se preocupa em aumentar o poder de uso das variáveis. Até agora, apenas as variáveis do Processing foram utilizadas. Como próximo passo, será mostrada a possibilidade do programador em definir e usar suas próprias variáveis.
Estrutura Condicional
No capítulo anterior, conhecemos os operadores relacionais e os operadores lógicos. Tais operadores permitem que um programa tome decisões sobre quais linhas de código podem ser executadas e quais linhas de código não podem ser executadas.
Em resumo, expressões relacionais são expressões que realizam operações de comparação entre dois valores de um mesmo tipo primitivo usando os operadores relacionais (==, >=, !=, <=, etc). Os operandos são variáveis, constantes ou expressões de qualquer tipo e o resultado da expressão é um valor lógico.
Os operadores relacionais são:
- <: Menor;
- >: Maior;
- <=: Menor ou igual;
- >=: Maior ou igual;
- ==: Igual;
- !=: Diferente.
As já citadas expressões lógicas, por sua vez, envolvem os operadores lógicos (||, &&, !). Os operandos são valores lógicos e o resultado da expressão é um valor lógico. A tabela verdade (combinação entre os operadores) é:
- true && true é igual a true;
- true && false é igual a false;
- false && true é igual a false;
- false && false é igual a false;
- true || true é igual a true;
- true || false é igual a true;
- false || true é igual a true;
- false || false é igual a false;
- !true é igual a false;
- !false é igual a true.
Estes resultados lógicos podem ser utilizados para executar ações apenas quando uma certa condição for satisfeita. Por exemplo, um programa pode desenhar ou não um objeto se o mouse for pressionado. O primeiro tipo de estrutura condicional é a seleção simples. Nesta estrutura, construída através da instrução if, se uma certa condição for verdadeira, a primeira instrução imediatamente abaixo da condição é executada. Caso a condição seja false, o comando é ignorado. Em inglês, “if” significa “se”.
if(condição)
comando a ser executado
No exemplo abaixo, a variável lógica mousePressed é usada como condição. Desta forma, o comando rect(width/3, height/3, width/3, height/3); só é executado caso mousePressed esteja com valor verdadeiro, ou seja, se o mouse for pressionado. Observe que o comando ellipse(width/3, height/3, width/3, height/3); sempre é executado e não é influenciado pelo if. Uma boa prática para dar a idéia que há uma relação entre o comando if e a linha posterior é fazer um pequeno deslocamento após o início da linha. Este deslocamento se chama indentação. Esta prática, no Processing, é apenas uma convenção estética. Em outras linguagens como Python, por exemplo, esta prática é obrigatória.

void draw()
{
background(255);
if(mousePressed)
rect(width/3, height/3, width/3, height/3);
ellipse(width/3, height/3, width/3, height/3);
}
Caso haja mais de um comando a ser executado estes comandos devem ser agrupados entre colchetes. Este agrupamento é chamado de bloco de instruções. Novamente, a indentação é relevante para facilitar a leitura. Abaixo, apenas enquanto qualquer tecla estiver pressionada, o fundo é mudado para a cor branca e o retângulo é desenhado.
void draw()
{
background(0);
if(keyPressed)
{
background(255);
rect(width/3, height/3, width/3, height/3);
}
}
A condição em uma seleção simples pode ser formada por uma expressão relacional. A seguir, apenas quando a posição em x do mouse for maior que a metade da tela, a linha é desenhada. O exemplo também demonstra outro estilo de indentação na qual a abertura da chaves é colocada logo após a definição da condição sem a quebra de linha.
void draw()
{
background(255);
if(mouseX>width/2) {
line(width/2, 0, width/2, height);
}
}
Para executar um fluxo alternativo de código apenas no caso da condição ser falsa, utiliza-se a estrutura de seleção composta. Neste caso, a palavra else é colocada logo após o fim do bloco de código definido pelo comando if. O bloco de instruções após o else só é executado quando a condição for falsa. É importante destacar que o fluxo principal e o fluxo alternativo tem execuções excludentes, ou seja, o fluxo alternativo nunca é executado após o fluxo principal.
O código abaixo ilustra o uso do else. O bloco do if só é executando quando o último botão do mouse pressionado pelo usuário for o botão esquerdo. A linha, então, é desenhada de cima para baixo e em um fundo branco. Caso contrário, ou seja, se não for o botão esquerdo, a linha desenhada é de baixo para cima em um fundo cinza.
void draw()
{
if(mouseButton==LEFT) {
background(255);
line(0, 0, width, height);
}
else {
background(128);
line(width, 0, 0, height);
}
}
Condições podem ser encadeadas. Neste caso, uma estrutura de seleção pode ser colocada dentro da outra. No exemplo abaixo, quando a primeira condição é falsa (mouseX<width/3) o segundo teste (mouseX<2*width/3) é feito. Caso este segundo teste também seja falso, daí sim a instrução background(255) é habilidada. Há, portanto, três fluxos no programa a seguir e os três fluxos são executados conforme o intervalo determinado pela variável mouseX.
void draw()
{
if(mouseX<width/3) {
background(0);
} else if(mouseX<2*width/3) {
background(128);
} else {
background(255);
}
line(width/3, 0, width/3, height);
line(2*width/3, 0, 2*width/3, height);
}
Exercício de Fixação 01 – Teste de mesa
Imagine a existência das variáveis a e b que podem assumir ou o valor zero ou o valor um. Complete a tabela abaixo, a partir de possíveis valores para a e b, segundo o código abaixo:
a b Comando Executado 0 0 println(”Z”); 0 1 1 0 1 1
Operadores lógicos também podem ser utilizados com as estruturas condicionais. Abaixo, um botão é criado conforme na área entre os pontos (30, 20) e (40, 35). Quando o usuário passa com o mouse sobre a região, sua cor de preenchimento é colocada com o valor branco (255). Caso contrário, o preenchimento é colocado com a cor preta (zero).
void draw()
{
// Cria um botão. Quando o mouse estiver dentro do intervalo,
// pinta o botão de branco
if(mouseX>=30 && mouseX<=40 && mouseY>=20 && mouseY<=35) {
fill(255);
}
else {
fill(0);
}
rect(30, 20, 10, 15);
}
Uma estrutura de seleção encadeada pode ser usada para representar os possíveis estados de um botão.Abaixo, as ações executadas quando o botão é clicado estão dentro do bloco posterior ao if(mousePressed).
void setup()
{
textFont(createFont(”Arial”, 10));
textAlign(CENTER);
}
void draw()
{
background(255);
// Cria um botão. Quando o mouse estiver dentro do intervalo,
// pinta o botão de branco
if(mouseX>=width/3 &&
mouseX<=2*width/3 &&
mouseY>=height/3 &&
mouseY<=2*height/3) {
if(mousePressed) {
fill(128);
text(”Ok!”, 10, 10);
}
else
fill(255);
}
else {
fill(0);
}
rect(width/3, height/3, width/3, height/3);
}
Em mais um exemplo de estrutura condicional encadeada, desta vez as variáveis de teclado são utilizadas:
void draw()
{
background(0);
if(keyPressed)
{
if(key==’r’ || key==’R')
{
background(255,0,0);
}
}
}
No seguinte, as teclas codificadas são consideradas. Neste caso, a instrução if(key==CODED) é necessária para verificar se a tecla é codificada. Cada if é responsável por verificar o estado de uma tecla
void setup()
{
textFont(createFont(”Arial”, 10));
textAlign(CENTER);
}
void draw()
{
background(128);
// Se for tecla codificada
if(key==CODED)
{
// Se for para cima
if(keyCode==UP)
{
text(”CIMA”, width/2, height/2);
} else if(keyCode==DOWN)
{
text(”BAIXO”, width/2, height/2);
}
}
}
Exercício de Fixação 02 – Botões
Faça um programa que implemente três botões na tela. Quando cada um destes botões é clicado, a cor de fundo da tela deve ser trocada.
A variável frameCount também poderia ser usada na construção de expressões relacionais e com o objetivo de controlar o andamento de uma animação. Entretanto, torna-se mais prática a utilização de variáveis criadas pelo próprio programador ao invés da frameCount. A próxima seção trata da criação deste tipo de variável. Posteriormente, verificaremos como utilizar tais variável em nossas estruturas de seleção.
Criação de variáveis em um programa
As variáveis criadas pelo programador também são armazenadas na memória do computador. Pode-se retornar à analogia que a memória corresponde a um armário recheado de gavetas. Para diferenciar uma gaveta de outra, é necessário por um rótulo em cada gaveta. O rótulo da gaveta corresponde ao identificador da variável. O conteúdo da gaveta corresponde ao valor associado à variável.
Para que se possa criar essas gavetas no armário, ou melhor, declarar as variáveis na memória é necessário configurar qual é o tipo de informação que pode ser armazenado em cada variável. Este processo de declaração é formado por três partes: tipo da variável, nome da variável e, opcionalmente, o valor inicial da variável após o comando de atribução (”=”). Nas linhas seguintes exemplifica-se a criação de três variáveis do tipo inteiro (int), uma após a outra:
int a = 1; // a começa com valor 1int b = 2; // b começa com valor 2int c = a + b; // c começa com valor 3int d; // d tem valor desconhecido.
O código acima demonstra que do lado direito do sinal de atribuição (”=”) pode-se ter uma expressão. No caso, a expressão aritmética “a + b” tem como resultado o valor 3. Assim, pode-se representar a memória do computador de maneira gráfica.

Observe que o valor da variável chamada d é desconhecido até a execução da última linha. Qualquer tentativa em utilizar a variável d levantará um erro de execução. Por exemplo, o código abaixo, tenta usar a variável d para calcular o valor de e.
int a = 1; // a começa com valor 1
int b = 2; // b começa com valor 2
int c = a + b; // c começa com valor 3
int d; // d tem valor desconhecido
int e = d * 2; // e é igual ao dobro de d, esta linha levanta um erro!
O Processing seleciona a linha com o erro e mostra a mensagem “The local variable d may not have been initialized”.

A inicialização da variável não necessariamente precisa ser feita durante a linha de declaração. A correção do código anterior, pode ser feita, portanto desta maneira:
int a = 1; // a começa com valor 1
int b = 2; // b começa com valor 2
int c = a + b; // c começa com valor 3
int d;
d= 4;
int e = d * 2; // e é igual ao dobro de d, ou seja 8.
A declaração das variáveis também pode ser resumida em uma linha.
int a, b, c, d, e;
a = 1; // a começa com valor 1
b = 2; // b começa com valor 2
c = a + b; // c começa com valor 3
d= 4;
e = d * 2; // e é igual ao dobro de d, ou seja 8.
O tipo inteiro não é o único tipo de dado disponível, o Processing também aceita outros tipos. Tais tipos armazenam diferentes objetos e obedecem a diferentes intervalos, ou seja, podem assumir diversos valores. Alguns exemplos:
- Inteiro (int): -2.147.483.648 a -2.147.483.647
- Ponto Flutuante (float): -3,4 * 10^38 a +3,4*10^38
- Caractere (char): 0 a 65535;
- Byte (byte): -128 a 127;
- Lógico (boolean): true ou false;
- Cor (color): 16 milhões de cores e 256 tonalidades de transparência;
- Fonte (PFont): Inúmeros tipos diferentes de fontes;
- Forma SVG (PShape): Inúmeros tipos diferentes de formas no formato SVG;
- Imagem (PImage): Diferentes tipos de imagens (.gif, .jpg, .png, .tga).
Após uma variável ser criada com um tipo de dado ele não pode ser trocado ou redefinido. Por exemplo, o código abaixo levanta o erro “Duplicate local variable a”.
float a= 12;
int a = 13;

Também não é possível misturar tipos que não sejam conversíveis. Por exemplo, o tipo ponto flutuante não “serve” dentro do tipo inteiro. A mensagem de erro dada é: “cannot convert from float to int”.
int a = 13.3; // Erro!
float a = 1;
int b = a + 12.4; // Erro!

Em muitas situações, porém, é necessária a conversão entre tipos de dados diferentes. A manipulação do tipo lógico (boolean) é um exemplo típico. Ele não é conversível implicitamente ao tipo inteiro. Para converter do tipo boolean para o tipo int, por exemplo, utiliza-se a função int.
boolean a = true;
int b = int(a);
Algumas outras funções de conversão disponíveis são:
- binary: Converte byte, char, int e color para string de notação binária;
- boolean: Converte de string (”true” e “false”) para valor lógico;
- byte: Conversão para byte;
- char: Conversão para char;
- float: Converte para float;
- hex: Converte um byte, char, int ou color para uma representação equivalente hexadecimal;
- int: Converte para número inteiro;
- str: Retorna a representação em string de tipos primitivos e arrays;
- unbinary: Converte uma representação binária no formato string para o inteiro equivalente;
- unhex: Converte uma representação hexadecimal no formato string para o inteiro equivalente.
Nomenclatura de Variáveis
Em relação aos nomes de variáveis, os exemplos mostrados até agora caracterizaram-se por usar apenas uma letra para dar nome à variável. Embora esta seja uma prática válida, é altamente recomendável a escolha de nomes significativos para descrever cada variável. Por exemplo, para representar uma variável que indica a cor do fundo de um programa algumas opções interessantes ao invés de “f” ou “c” seriam:
- fundo
- corFundo
- corDeFundo
Nomes como “CORDEFUNDO”, “CorDeFundo” e “cordefundo” embora sejam válidos para a linguagem de programação, fogem de uma certa convenção de nomenclatura recomendável para facilitar a leitura de seus programas. Esta convenção depende de cada linguagem. No Processing, utiliza-se o chamado CamelCase, recomendando-se que:
- O nome de todas as variáveis seja iniciado com letra minúscula e nunca por um número;
- Se o nome da variável for composto por mais de uma palavra, as palavras seguintes devem ter sua primeira letra maiúscula;
- Variáveis que nunca mudam de valor durante a execução de um programa, ou, na prática, constantes são nomeadas de maneira diferente e todas as letras devem ser capitalizadas. Por exemplo: CORNER, CENTER, indicam valores constantes.
Também se deve salientar que alguns caracteres não podem ser usados para dar nome às variáveis. Neste conjunto se incluem os espaços, caracteres especiais ($, %, &, * , -, etc) e caracteres acentuados. Além disso, as variáveis também não podem ser nomeadas com as palavras-reservadas da linguagem Processing. E, embora seja possível, é altamente não recomendável utilizar o nome de funções já existentes para dar nome. Ou seja, “rect” e “ellipse” são nomes que devem ser evitados e “int” e “float” são inválidos.
Escopo de variáveis
Uma variável possui uma área de validade, ou seja, sua existência é limitada a um bloco de código. Esta validade é chamada de escopo da variável.
No caso do modo contínuo do Processing, para criar uma variável que seja vista por todo o programa, sua criação deve ser feita fora dos blocos setup e draw. Por exemplo, no código abaixo, a variável x pode ser trabalhada tanto pelo setup quanto pelo draw.
int x;
void setup()
{
x = width;
strokeWeight(10);
}
void draw()
{
background(255);
point(x, height/2);
x = x – 1;
}
Se uma variável é definida dentro de um bloco, ela não é enxergada pelo outro. No exemplo abaixo, o Processing levanta o erro “Cannot find anything named ‘n’”, denotando que a variável n, dentro do bloco draw é desconhecida. Em outras palavras, o escopo da variável n é o bloco setup.

void setup()
{
int n = 0;
strokeWeight(10);
}
void draw()
{
background(255);
point(n, height/2);
n = n + 1;
}
Observe que blocos podem ser criados através da abertura e fechamento de chaves. No exemplo abaixo, a variável cor só existe dentro do if. Este estilo de codificação pode criar uma confusão na leitura do código. Recomenda-se, portanto, a organização da criação das variáveis. Assim, sua definição deve ser feita no início dos blocos draw e setup no caso de variáveis que devem ser usadas apenas nestes blocos e fora do setup e draw no caso de variáveis que devem ser compartilhadas pelos dois blocos.
void draw()
{
if(mousePressed)
{
color c = color(255);
}
background(c);
}
Na seção a seguir, exemplificam-se alguns usos de variáveis no Processing e, principalmente, sua utilização conjunta à estrutura condicional.
Exemplos de uso de variáveis
Variáveis podem ser usadas para representar a posição de um objeto na tela. No exemplo abaixo, as variáveis x e y indicam a posição em x e y da construção de um ponto.
Em setup os valores de x e y são, respectivamente, inicializados com width/2 e height/2, ou seja, o ponto é desenhado no centro da tela.
float x;
float y;
void setup()
{
x = width/2;
y = height/2;
strokeWeight(10);
}
void draw()
{
background(255);
point(x,y);
}
As variáveis x e y podem ser alteradas a cada chamada do draw. Esta atualização pode ser feita, por exemplo, com a instrução x=x+1. Esta instrução, a cada chamada do draw, incrementa o valor de x em uma unidade. Por exemplo, na primeira chamada ao draw, ou seja, no primeiro frame, x é igual a 50. A partir daí, x = 50 +1, ou x fica com valor 51. Como a modificação de x em cada frame é de uma posição, pode-se dizer que sua velocidade em x é de 1 pixel por frame.
float x;
float y;
void setup()
{
x = width/2;
y = height/2;
strokeWeight(10);
println(x);
}
void draw()
{
background(255);
point(x,y);
x = x + 1;
println(x);
}
No próximo exemplo, a velocidade do objeto é dependente da posição do mouse. Desta forma, se a posição do mouse estiver à esquerda do objeto a velocidade é negativa. Caso contrário, a velocidade é positiva.
float x;
float y;
void setup()
{
x = width/2;
y = height/2;
strokeWeight(10);
frameRate(30);
}
void draw()
{
background(255);
point(x,y);
// Faz com que o objeto siga o mouse (eixo x)
if(mouseX<x)
x = x – 1;
else if(mouseX>x)
x = x + 1;
// Faz com que o objeto siga o mouse (eixo y)
if(mouseY<y)
y = y – 1;
else if(mouseY>y)
y = y + 1;
}
O teclado também pode ser utilizado como condição para a modificação de uma variável. A seguir, as teclas controlam a modificação de x ou y.
float x;
float y;
void setup()
{
x = width/2;
y = height/2;
strokeWeight(10);
frameRate(30);
}
void draw()
{
background(255);
point(x,y);
// Se a tecla for codificada e
// pressionada
if(key==CODED && keyPressed)
{
// Para cima, altera o valor de y em -1
if(keyCode==UP)
{
y = y – 1;
}
// Para baixo, altera o valor de y em +1
else if(keyCode==DOWN)
{
y = y + 1;
}
// Para esquerda, altera o valor de x em -1
else if(keyCode==LEFT)
{
x = x – 1;
}
// Para direita, altera o valor de x em +1
else if(keyCode==RIGHT)
{
x = x + 1;
}
}
}
Executar!
Além dos tipos básicos, as variáveis também podem conter objetos mais complexos como fontes e imagens. A função createFont, no exemplo a seguir, retorna uma variável do tipo PFont. Essa variável é usada no bloco draw para desenhar a cada frame um texto diferente. A condição (frameCount%2==0) a cada frame habilita um bloco diferente. Quando frameCount é par, a condição é verdadeira e o fluxo principal é executado. No caso de frames ímpares o fluxo alternativo é executado.
PFont fonte1;
PFont fonte2;
void setup()
{
fonte1 = createFont(”Arial”, 15);
fonte2 = createFont(”Times New Roman”, 20);
textAlign(CENTER);
frameRate(5);
}
void draw()
{
background(128);
// Em frames pares, mostra a fonte arial
if(frameCount % 2==0)
{
textFont(fonte1);
text(”Arial”, width/2, height/2);
}
else // Em frames ímpares, mostra a times
{
textFont(fonte2);
text(”Times”, width/2, height/2);
}
}
Outro tipo de variável que o Processing aceita é a variável de imagem. Uma imagem é representada pelo tipo PImage. Para carregar uma imagem é necessária a chamada à função loadImage passando como parâmetro o nome do arquivo de imagem. A exibição da imagem é controlada pela função image. Tal função permite a escolha da posição da imagem na tela e, opcionalmente, de sua altura e largura. No exemplo a seguir, o arquivo “aviao.png” é exibido.
Para colocar este arquivo dentro do projeto para que Processing consiga enxergá-lo, selecione o menu Sketch > Add file… . O arquivo será colocado em uma pasta chamada data dentro da pasta do projeto.
// Variável de imagem
PImage img;
// Carrega a imagem
img = loadImage(”aviao.png”);
// Exibe a imagem na posição 0,0
image(img,0,0);
Imagem inserida (originalmente de SpriteLib GPL – observe a licença desta imagem no site!).
No próximo exemplo, a exibição da imagem é controlada a partir da posição do mouse. A chamada a imageMode(CENTER) faz com que o desenho da imagem seja centralizado em relação à posição do mouse.
// Variável de imagem
PImage img;
void setup()
{
size(300, 200);
// Carrega a imagem
img = loadImage(”aviao.png”);
// O modo de desenho da imagem é centralizado
imageMode(CENTER);
}
void draw()
{
// Oculta o cursor
noCursor();
// Cor de fundo igual ao fundo da imagem
background(0,67,171);
// Exibe a imagem na posição do mouse
image(img,mouseX,mouseY);
}
Por enquanto, observe que só nos preocupamos em carregar e mostrar as imagens. Futuramente, veremos como uma imagem pode ser alterada através de filtros ou processada pixel a pixel.
Para saber mais
Reas, Casey. Fry, Ben. Processing: A Programming Handbook for Visual Designers and Artists.
51 a 59 – decisão.




















Comentários