[Trabalho 2] Quadro animado por meio de uma interface
Agora o quadro de Geraldo de barros terá uma nova forma, que pode ser controlada pelo usuário a partir da interface gráfica do controlP5 para o Processing P3, além de poder ter sua imagem salva em diferentes formatos
ao se pressionar uma tecla.
Link de acesso ao arquivo .pde no Google Drive.
Código completo:
//PRIMEIRA ABA
/* QUADRO ANIMADO A PARTIR DE UMA INTERFACE CONTROLP5
- Pelo menos dois parâmetros sendo alterados, por elemento de interface:
alterar a posição, "inverter" o quadro, mantendo as proporções
escolher as cores que o formam
alterar o tamanho do quadro sem perder as proporções
- Salva a imagem em formatos diferentes e cria um arquivo de texto com informações
Na hora que o usuário desejar
- Armazena informações sobre o arquivo através da classe
Deve: criar um arquivo de texto com data, copyright simples e formato da imagem */
//___________________________________________________________________________________
//Importação da biblioteca para o Processing
import controlP5.*;
//Criação de nova instância do tipo ControlP5
ControlP5 cp5;
//Definirá o tamanho do quadro
Slider tam;
//Definirá as posições dos elementos
Slider move;
//Definirão as cores do quadro
Slider red;
Slider gre;
Slider blu;
int cont = 0; //Contador para o salvamento de imgs e textos
void setup(){
size(900,563);
cp5 = new ControlP5(this);
//Definições dos sliders que alterarão os elementos do quadro:
//Tamanho do quadro:
tam = cp5.addSlider("tamanho");
tam.setRange(200,563) /*O tamanho mínimo do quadro será 200, enquanto o máximo será 563*/
.setValue(563) /*O quadro iniciará no tamanho máximo*/
.setPosition(590,210)
.setSize(200,20);
//Cores:
red = cp5.addSlider("R");
red.setRange(0, 255)
.setValue(0)
.setPosition(590, 140)
.setSize(200, 20);
gre = cp5.addSlider("G");
gre.setRange(0, 255)
.setValue(0)
.setPosition(590, 160)
.setSize(200, 20);
blu = cp5.addSlider("B");
blu.setRange(0, 255)
.setValue(0)
.setPosition(590, 180)
.setSize(200, 20);
//Posicionamento:
move = cp5.addSlider("inverte");
move.setRange( 1, (tam.getValue()/2) ) /*Os pontos X dos quadriláteros tem o limite máximo de metade do tamanho do quadro para se moverem*/
.setValue(1)
.setPosition(590, 100)
.setSize(200, 20);
}
void draw (){
background (100);
Quadro();
//Instruções ao usuário
String titulo = "Altere o que quiser.";
textSize(20);
fill(200);
text(titulo, 580, 30);
//Instruções ao usuário após ele alterar algum elemento, em seus mínimos
if (move.getValue() > 1 || red.getValue()>=17 || gre.getValue()>=21 || blu.getValue()>=28 ||tam.getValue()<563){
String mensagem1 = "Que bonito!";
String mensagem2 = "Geraldo de Barros estaria orgulhoso de você.";
String mensagem3 = "Para salvar em .PNG, tecle 'p'";
String mensagem4 = "Para salvar em .TIFF, tecle 't'";
String mensagem5 = "Para salvar em .JPEG, tecle 'j'";
textSize(14);
fill(200);
text(mensagem1, 580, 450);
text(mensagem2, 580, 470);
fill(255);
text(mensagem3,580,510);
text(mensagem4,580,530);
text(mensagem5,580,550);
}
}
void keyPressed() {
/*
- Cada tecla salva o frame em um formato de imagem diferente
- Cada uma das condições realiza funções semelhantes, com a mudança mínima do
formato de imagem.
- Temos uma variável contadora que é incrementada a cada vez que se pressiona
uma tecla, para não haver sobreescrita e perda de arquivos.
- A variável contadora torna mais fácil a manipulação dos nomes dos arquivos
de texto e imagem do que a contagem de número de frames
- Cria-se o novo objeto da classe ArquivoInfo a cada vez que uma das teclas
é pressioada, e tem como atributos o nome dos arquivos de texto, imagem e seu
formato.
- Cria-se as strings necessárias para o arquivo de texto na classe ArquivoInfo
- Utiliza-se o método de retornar detalhes da classe Arquivo Info (info.retornaDet())
para executá-lo na função saveStrings() e adicionar ao arquivo de texto todas as informações
necessárias de data, copyright, nome da imagem e seu formato.*/
if(key == 'p'){
String nomeImg = "designDeAzulejosImg"+cont;
String nometxt = "designDeAzulejosTxt"+cont;
String formato = "PNG";
ArquivoInfo info = new ArquivoInfo(nomeImg,nometxt,formato);
saveFrame(nomeImg+".png");
saveStrings(nometxt+".txt",info.retornaDet());
cont++;
}
if(key == 't'){
String nomeImg = "designDeAzulejosImg"+cont;
String nometxt = "designDeAzulejosTxt"+cont;
String formato = "TIFF";
ArquivoInfo info = new ArquivoInfo(nomeImg,nometxt,formato);
saveFrame(nomeImg+".tif");
saveStrings(nometxt+".txt",info.retornaDet());
cont++;
}
if(key == 'j'){
String nomeImg = "designDeAzulejosImg"+cont;
String nometxt = "designDeAzulejosTxt"+cont;
String formato = "JPEG";
ArquivoInfo info = new ArquivoInfo(nomeImg,nometxt,formato);
saveFrame(nomeImg+".jpg");
saveStrings(nometxt+".txt",info.retornaDet());
cont++;
}
}
//___________________________________________________________________________
//SEGUNDA ABA
/*A classe ArquivoInfo cria objetos que conterão as informações necessárias para
o arquivo de texto, criado juntamente com as imagens
Recebe como atributos o nome da imagem, seu formato e o nome do arquivo de texto.
Adiciona informações de dia, mês e ano de criação, além de um copyright
Reúne as Strings de informação num vetor de strings no método de retornar detalhes ( retornaDet() )
Esse método retorna as strings ao código principal ao ser chamado por meio do objeto (info), ao
ser pressionada alguma tecla*/
class ArquivoInfo{
//strings locais com o mesmo nome das strings do código principal
String imgNome;
String txtNome;
String formato;
ArquivoInfo(String imgNome, String txtNome, String formato){
/*Inicializa-se as variáveis da classe pelo construtor, equivalendo seus valores
aos valores presentes nas strings do código principal*/
this.imgNome = imgNome;
this.txtNome = txtNome;
this.formato = formato;
}
String [] retornaDet (){
//Adiciona-se os "det"alhes presentes no arquivo de texto
String detimagem = "Nome da imagem: " + imgNome + "\n";
String detformato = "De formato: "+formato+"\n";
String detTxt = "Nome do arquivo de texto: "+ txtNome + "\n";
String copyR = "O quadro original pertence a Geraldo de Barros, mas você agora pode dizer que virou um designer de Azulejos.\n";
int d = day();
int m = month();
int y = year();
int h = hour();
int min = minute();
String data = "criado em: "+String.valueOf(d) +"/"+String.valueOf(m)+"/"+String.valueOf(y)+" às: "+String.valueOf(h)+":"+String.valueOf(min)+"\n";
//Cria-se o array para armazenar as strings em ordem para o arquivo de texto
String retorno[] = new String [5];
retorno[0] = detimagem;
retorno[1] = detformato;
retorno[2] = detTxt;
retorno[3] = data;
retorno[4] = copyR;
return retorno; //retorna o array de strings ao documento de texto que é criado ao se pressionar uma tecla
}
}
//_______________________________________________________________________
//TERCEIRA ABA
/*
Aqui cria-se o quadro e seus elementos.
As proporções do quadro são as seguintes:
- A largura dos quadriláteros sempre são 1/8 do lado da imagem (img/8),
- Por esse motivo há a variável larg, que contém esse valor (imgW/8)
- Os quadriláteros mais externos são a base para o posicionamento dos seguintes
- O espaço entre a largura de um quadrilátero e outro são: ou a própria largura (larg = imgW/8), ou 0,
alternando-se.
- O espaço entre as alturas de cada quadrilátero para o seu seguinte são particulares, não tendo um
padrão percebido imediatamente. Usa-se, porém, frações da largura e do lado da imagem como unidade de medida
- Para se ter uma animação mais fluida, em casos que os pontos X esquerdo (lX)
e X direito (rX), que são as larguras dos quadriláteros, estivessem mais à frente
ao serem incrementados com o valor de "anda" que os pontos X Superior (topX) e
X inferior (btmX), parecendo estar mais rápidos, diminui-se em 1/2 ou menos o valor da
variável de movimento, dependendo do tamanho do quadrilátero.
*/
void Quadro() {
//imgW para largura do quadro
//imgH para altura do quadro
float imgW = tam.getValue();
float imgH = tam.getValue();
//_________ Definições de cores _______________
//As cores originais da obra estão armazenadas nesta lista, alternando conforme as posições
//da esquerda para a direita.
color [] cor = {color (255), color (163), color(255), color (163), color (255), color (163)};
/*Estas variáveis armazenarão os valores de cada slider RGB, e serão transformadas em valores de cor RGB*/
float r = red.getValue();
float g = gre.getValue();
float b = blu.getValue();
/*Condição para definição de cores para os quadriláteros:
Se os valores de cor forem maiores que os do plano de fundo da obra original
Preenche-se os vetores com com os valores das cores novas, que também se alteram
seguindo o esquema visual de posicionamento.
Vão do mais escuro ao mais claro
*/
if (r >= 17 || g >= 21 || b >= 28) {
for (int i = 0; i<6; i++) {
if (i%2 ==0) {
cor[i] = color(r*(i+2), g*(i+2), b*(i+2));
} else {
cor[i] = color(r, g, b);
}
}
}
/*Condição para a definição de cores do plano de fundo e tamanho do quadro:
Caso as cores recebam um valor maior que a cor do plano de fundo original,
O plano de fundo segue as mesmas matizes, com luminosidade mais baixa, para
distinguir-se dos quadriláteros.
O tamanho do plano de fundo dita o posicionamento de todos os quadriláteros
e o tamanho do quadro em si, podendo ir de 200 a 563
*/
if (r >= 17 || g >= 21 || b >= 28) {
fill(r-50, g-60, b-40);
} else {
fill(r, g, b);
}
rect(0, 0, imgW, imgH);
//_________________DEFINIÇÕES DE POSICIONAMENTO____________
float topX, lX, btmX, rX;
float topY, lY, btmY, rY;
float larg = imgW/8;
float anda;
//Cria-se a condição para o incremento da variável anda
//a partir dos valores do slider "move"
if (move.getValue() > 1){
anda = move.getValue();
} else {
anda = 0;
}
/*
A partir daqui serão criados os quadriláteros individualmente
Pois cada uma de suas animações e posições possuem particularidades
Todos os quadriláteros são posicionados com seus pontos em ordem
anti-horária: (Topo, esquerdo, inferior, direito)
Quadriláteros posicionados no lado esquerdo do quadro tem seus topos
movidos para a esquerda, enquanto os da direita, movem-se para a direita.
Os pontos esquerdo e direito de cada quadrilátero seguem temporariamente
em uma direção contrária a dos topos, para alinharem-se a eles, depois
seguem a mesma direção.
*/
//_____QUADRILÁTERO 01- GRANDE - ESQUERDO ______
topX = imgW/2 - anda;
topY = 0;
lX = anda;
lY = imgH/2;
btmX = imgW/2 - anda;
btmY = imgH;
rX = larg + anda;
rY = imgH/2;
/*Cria-se a condição para que nem o topo nem o inferior ultrapassem
a borda esquerda da imagem e para que nem o lado esquerdo e o direito
ultrapassem a metade do quadro (imgW/2), fixando suas posições
*/
if(lX > imgW/2 || rX > imgW/2 || topX < 0 || btmX < 0){
lX = imgW/2;
rX = imgW/2 - larg;
topX = 0;
btmX = 0;
}
fill(cor[0]); //recebe a primeira cor do array
noStroke();
quad(topX, topY, lX, lY, btmX, btmY, rX, rY); //Em ordem anti-horária
//____QUADRILÁTERO 02 - MÉDIO - ESQUERDO____
topX = (imgW/2 - anda*2)+(imgW/16); //Seu topo e seu inferior se movem mais depressa
topY = larg; //que seus lados direito e esquerdo
lX = larg - (anda/5);
btmX = (imgW/2 - anda*2)+(imgW/16);
btmY = imgH-(larg);
rX = (larg - (anda/5)) + larg ;
/*
Cria-se a condição para que, caso o lX e o rX tenham posições menores que os valores
de 0 e da largura (img/8), ou seja, caso chegem à borda esquerda do quadro, eles
invertam o valor de seus movimentos, movendo-se nas direções contrárias.
*/
if (lX <= 0 || rX < larg){
rX = larg + anda+5;
lX = rX - larg;
if(rX >= imgW/2){ //Mas caso o rX ultrapasse o limite da metade do quadro,
rX = larg - anda+5; //volta a mover-se na direção contrária
}
}
/*
Cria-se a condição para fixar as posições do quadrilátero, caso o limite seja
atingido pelo topo e pelo inferior, pelo lado esquerdo do quadro, e pelo
lX e rX pela metade do quadro.
*/
if (topX < 0 || btmX < 0 || rX > (imgW/2 - 2*larg) || lX > imgW/2 - larg){
topX = 0;
btmX = 0;
rX = (imgW/2 - 2*larg);
lX = rX + larg;
}
fill(cor[1]);
noStroke();
quad(topX, topY, lX, lY, btmX, btmY, rX, rY);
//_________QUADRILÁTERO 3 - PEQUENO - ESQUERDO_________________
/*É o quadrilátero com a maior particularidade dos 3 esquerdos, pelo
posicionamento de seus pontos inferiores e superiores*/
topX = (imgW/2)+larg/2 - anda*2;
topY = topY+ larg + larg/3;
btmX = topX;
btmY = btmY- (larg + larg/3);
rX = imgW/2 - larg/3 + anda;
lX = imgW/2 - larg + anda;
//Condição para o limite de movimento de rX e lX
//também delimitados pelo meio da imagem (imgW/2)
if (rX >= imgW/2){
rX = imgW/2 - larg/3 - anda;
lX = rX - larg;
if (rX < imgW/2 - 2*larg){
rX = imgW/2 - 2*larg;
lX = rX - larg;
topX = 0;
btmX = 0;
}
}
fill(cor[2]);
noStroke();
quad(topX, topY, lX, lY, btmX, btmY, rX, rY);
//___________LADO DIREITO________________
/*Os quadriláteros do lado direito movem-se de maneira oposta aos do lado
esquerdo, porém possuem comportamentos semelhantes. Não podem ultrapassar
o limite do meio da imagem, nem da borda direita*/
//_________QUADRILÁTERO 01 - GRANDE - DIREITO_________________
topX = imgW/2 + anda;
topY = 0;
lX = (imgW-larg) - anda;
btmX = imgW/2 + anda;
btmY = imgH;
rX = imgW - anda;
//Cria-se a condição de limite para topX, btmX, lX e rX
if (lX < imgW/2 || rX < imgW/2 || topX > imgW || btmX > imgW){
lX = imgW/2;
rX = imgW/2 + larg;
topX = imgW;
btmX = imgW;
}
fill(cor[3]);
noStroke();
quad(topX, topY, lX, lY, btmX, btmY, rX, rY);
//____________QUADRILÁTERO 02 - MÉDIO - DIREITO______________
/*Agora a maior particularidade pertence a este quadrilátero, por
seu posicionamento de topo e inferior não estarem dentro das proporções
da largura, tendo que utilizar o lado da imagem como unidade de medida*/
topY = topY+imgW/5;
rX = imgW + anda - imgW/4;
lX = (imgW-larg) + anda - imgW/4;
btmY = btmY-imgW/5;
//Condição para o limite da largura esquerda e direita
if (lX <= imgW/2 || rX <= imgW/2-larg){
rX = (imgW/2-larg) - anda;
lX = rX - larg;
}
if (rX > (imgW - 2*larg) || lX > imgW/2 - larg){
rX = imgW/2 + 2*larg;
lX = imgW/2 + larg;
}
//Condição para o limite dos pontos inferiores e superiores
if (topX > imgW || btmX > imgW){
topX = imgW;
topY = topY+imgW/3;
btmX = imgW;
btmY = topY+imgW/3;
}
fill(cor[4]);
noStroke();
quad(topX, topY, lX, lY, btmX, btmY, rX, rY);
//________QUADRILÁTERO 3 - PEQUENO - DIREITO ____________
/*O último quadrilátero é o menor de todos e possui particularidades
na posição de seu topo e de seu inferior, tendo frações da largura como unidade
de medida*/
topY = imgH/2 - (larg/2 + larg/3);
btmY = imgH/2 + (larg/2 + larg/3);
topX = imgW/2 + anda;
btmX = topX;
lX = (imgW/2 + larg/3) - anda;
rX = ((imgW-larg) - imgW/4) - anda;
/*Condição para o incremento de seu lX e seu rX*/
if (lX<imgW/2){
lX = imgW/2 + anda;
rX = imgW/2+larg + anda;
}
//condição para o limite de posição de lX e rX
if (lX > imgW - (larg/2 + larg/3)){
lX = imgW - larg/3;
rX = lX - larg;
topX = topX + anda/2; //Aqui aumenta-se um pouco a velocidade do topX e do btmX
btmX = btmX + anda/2; //para manter a fluidez do movimento
}
//Condição para o limite de posição de topX e btmX
if (topX > imgW){
topX = imgW;
btmX = imgW;
}
fill(cor[5]);
noStroke();
quad(topX, topY, lX, lY, btmX, btmY, rX, rY);
}

Comentários
Postar um comentário