Na aula sobre chroma key, foi pedido que fosse produzido uma aplicação no Processing que simulasse o efeito de um knob, que é um aparelho que faz um efeito de dissolver uma imagem para outra apenas mexendo uma manivela de forma gradual.
Segue abaixo o código comentado com um gif no final demonstrando o efeito.
//variáveis das imagens
PImage img1;
PImage img2;
/*variáveis que irão armazenar o valor RGB de cada uma das imagens que o laço
percorrer*/
float r1, g1, b1, r2, g2, b2;
//variável que irá guardar a posição do pixel da imagem quando percorre o laço
int pos;
//modificadores que irão variar dependendo de mouseY
float a, d;
void setup(){
size(320, 240);
img1 = loadImage("original.jpg");
img2 = loadImage("original2.png");
}
void draw(){
loadPixels();
/*primeira imagem, que terá o "a" como modificador, será uma fração de mouseY em
relação o tamanho da tela*/
a = float(mouseY)/height;
d = 1 - a;
//segunda imagem, o mesmo que foi comentado anteriormente
d = float(mouseY)/height;
a = 1 - d;
/*o laço percorre ambas as imagens, guardando os valores dos respectivos pixels
em suas variáveis para formar a imagem final*/
for( int x=0; x<320; x++){
for(int y=0; y <240; y++){
pos = y*320 + x;
//recebimento dos valores RGB da primeira imagem
r1 = a*red(img1.pixels[pos]);
g1 = a*green(img1.pixels[pos]);
b1 = a*blue(img1.pixels[pos]);
//recebimento dos valores RGB da segunda imagem
r2 = red(img2.pixels[pos])*d;
g2 = green(img2.pixels[pos])*d;
b2 = blue(img2.pixels[pos])*d;
//formação da imagem, dependendo da posição do mouse
pixels[pos] = color(r1 + r2, g1 + g2, b1 + b2);
}
}
updatePixels();
}
terça-feira, 2 de fevereiro de 2016
segunda-feira, 1 de fevereiro de 2016
O olho do observador
Na aula de arco tangente, foi pedido para a sala de aula que produzisse uma aplicação no processing que simulasse um olho que seguiria o cursor do mouse.
Para isto, bastava calcular a inclinação que uma reta teria do centro até a posição que está o mouse, depois fazer duas circunferências: uma que represente a parte externa do olho e outra a pupila, que seguiria o cursor do mouse se limitando a ficar dentro da circunferência externa.
Durante a produção deste código, me lembrei do conhecido monstro de Dungeons and Dragons, o Beholder, e resolvi ilustrar o efeito colocando uma figura dele.
Segue o código abaixo comentado.
PImage beholder;
//variável que considera mouseX e o comprimento da tela
float a = 0;
//variável que considera mouseY e a altura da tela
float b = 0;
//variável que armazena o arco tangente
float arctan;
void setup(){
size(600,600);
beholder = loadImage("beholder.jpg");
}
void draw(){
fill(255);
background(255);
//imagem do beholder
image(beholder, 15, 50);
//circunferência externa
ellipse(width/2, height/2, 150,150);
noStroke();
fill(0);
arctan = atan2(mouseY-height/2, mouseX-width/2);
if(arctan<0){
arctan += 2*PI;
}
a = mouseX - width/2;
b = mouseY - height/2;
//distância máxima que a "pupila" percorre
a = 75*a/300*cos(arctan);
b = 75*b/300*sin(arctan);
//circunferência de dentro é feita considerando os quatro quadrantes dela
//primeiro quadrante
if(arctan>=0 && arctan<PI/2){
ellipse(width/2 + a, height/2 + b, 25, 25);
//segundo quadrante
}else if(arctan>=PI/2 && arctan<PI){
ellipse(width/2 - a, height/2 + b, 25, 25);
//terceiro quadrante
}else if(arctan>=PI && arctan<3*PI/2){
ellipse(width/2 - a, height/2 - b, 25, 25);
//quarto quadrante
}else if(arctan>=3*PI/2 && arctan<2*PI){
ellipse(width/2 + a, height/2 - b, 25, 25);
}
}
Para isto, bastava calcular a inclinação que uma reta teria do centro até a posição que está o mouse, depois fazer duas circunferências: uma que represente a parte externa do olho e outra a pupila, que seguiria o cursor do mouse se limitando a ficar dentro da circunferência externa.
Durante a produção deste código, me lembrei do conhecido monstro de Dungeons and Dragons, o Beholder, e resolvi ilustrar o efeito colocando uma figura dele.
Segue o código abaixo comentado.
PImage beholder;
//variável que considera mouseX e o comprimento da tela
float a = 0;
//variável que considera mouseY e a altura da tela
float b = 0;
//variável que armazena o arco tangente
float arctan;
void setup(){
size(600,600);
beholder = loadImage("beholder.jpg");
}
void draw(){
fill(255);
background(255);
//imagem do beholder
image(beholder, 15, 50);
//circunferência externa
ellipse(width/2, height/2, 150,150);
noStroke();
fill(0);
arctan = atan2(mouseY-height/2, mouseX-width/2);
if(arctan<0){
arctan += 2*PI;
}
a = mouseX - width/2;
b = mouseY - height/2;
//distância máxima que a "pupila" percorre
a = 75*a/300*cos(arctan);
b = 75*b/300*sin(arctan);
//circunferência de dentro é feita considerando os quatro quadrantes dela
//primeiro quadrante
if(arctan>=0 && arctan<PI/2){
ellipse(width/2 + a, height/2 + b, 25, 25);
//segundo quadrante
}else if(arctan>=PI/2 && arctan<PI){
ellipse(width/2 - a, height/2 + b, 25, 25);
//terceiro quadrante
}else if(arctan>=PI && arctan<3*PI/2){
ellipse(width/2 - a, height/2 - b, 25, 25);
//quarto quadrante
}else if(arctan>=3*PI/2 && arctan<2*PI){
ellipse(width/2 + a, height/2 - b, 25, 25);
}
}
Relógio de segundos
Na aula que foi apresentado o conceito de coordenadas polares, foi pedido como tarefa que os alunos produzissem no Processing uma aplicação que demonstrasse ser um relógio de segundos tendo seu ponteiro indicando o tempo correto utilizando a função millis(), a qual é uma função .
Considerando que o ponteiro irá ter sua extremidade percorrendo uma circunferência (o formato do relógio é redondo) e pra cada segundo o ângulo em radianos considerado é 2*PI/60 (referente aos sessenta segundos de um minuto), podemos chamar a função millis() e considerar que, dentro de um laço, enquanto millis (que será iniciado no primeiro frame da animação) dividido por 1000(resultando em um segundo no tempo que se passou) for diferente de 0, a linha será redesenhada em seguida.
Na coordenada X do fim da linha, será considerada o cosseno do ângulo (em radianos) multiplicado pelo tempo(uma variável que é incrementada a cada vez que o código é executado) menos PI/2 (isso é feito porque o ponteiro é iniciado no meio da parte superior da circunferência). Já a coordenada Y é considerado o seno do ângulo sob as mesmas condições já citadas.
Segue abaixo o código comentado.
float tempo = 0;
float ang = 2*PI/60;
void setup(){
size(600,600);
}
void draw(){
background(255);
//aqui é esperado um segundo antes do código continuar a ser lido
while (millis()%1000 != 0){}
//coloração da circunferência
stroke(0);
//circunferência que representa o relógio
ellipse(width/2, height/2, 400, 400);
//coloração do ponteiro
stroke(125, 0, 0);
//cálculo de onde a linha será desenhada a cada segundo
line(width/2,height/2,width/2 + 180*cos(tempo*ang - PI/2),height/2 + 180*sin(tempo*ang - PI/2));
tempo++;
}
Considerando que o ponteiro irá ter sua extremidade percorrendo uma circunferência (o formato do relógio é redondo) e pra cada segundo o ângulo em radianos considerado é 2*PI/60 (referente aos sessenta segundos de um minuto), podemos chamar a função millis() e considerar que, dentro de um laço, enquanto millis (que será iniciado no primeiro frame da animação) dividido por 1000(resultando em um segundo no tempo que se passou) for diferente de 0, a linha será redesenhada em seguida.
Na coordenada X do fim da linha, será considerada o cosseno do ângulo (em radianos) multiplicado pelo tempo(uma variável que é incrementada a cada vez que o código é executado) menos PI/2 (isso é feito porque o ponteiro é iniciado no meio da parte superior da circunferência). Já a coordenada Y é considerado o seno do ângulo sob as mesmas condições já citadas.
Segue abaixo o código comentado.
float tempo = 0;
float ang = 2*PI/60;
void setup(){
size(600,600);
}
void draw(){
background(255);
//aqui é esperado um segundo antes do código continuar a ser lido
while (millis()%1000 != 0){}
//coloração da circunferência
stroke(0);
//circunferência que representa o relógio
ellipse(width/2, height/2, 400, 400);
//coloração do ponteiro
stroke(125, 0, 0);
//cálculo de onde a linha será desenhada a cada segundo
line(width/2,height/2,width/2 + 180*cos(tempo*ang - PI/2),height/2 + 180*sin(tempo*ang - PI/2));
tempo++;
}
Fazer um polígono com qualquer número de lados
Dentre as atividades passadas para serem feitas e postadas neste blog, foi pedido que fosse produzido uma função no Processing que recebesse um número e retornasse um polígono com o número de lados relativo ao número que foi recebido.
Para a produção deste polígono, consideramos como base uma circunferência. Na produção deste polígono, temos que considerar que cada ângulo em radianos formado entre os lados deste polígono é referente a divisão de 2*PI radianos e o número de lados deste polígono.
Em seguida, é feito um laço que produz linhas que conectam os vértices do polígono. Para a coordenada X é considerado o cosseno do ângulo e para a coordenada Y é considerado o seno do ângulo.
O código comentado pode ser visto abaixo.
//raio da circunferência
int raio = 200;
//número de lados do polígono
int lados = 6;
void setup(){
size(600,600);
//ângulo do lado interno do polígono
float ang = 2*PI/lados;
/*circunferência que serve de base, retire o comentário
para ver a circunferência ao executar o código*/
//ellipse(width/2,height/2,2*raio,2*raio);
//cálculo do local que fica cada vértice do polígono
for (int i =0;i<lados;i++){
line(width/2+raio*cos(i*ang),height/2 + raio*sin(i*ang), width/2 + raio*cos((i+1)*ang),height/2 + raio*sin((i+1)*ang));
}
}
Para a produção deste polígono, consideramos como base uma circunferência. Na produção deste polígono, temos que considerar que cada ângulo em radianos formado entre os lados deste polígono é referente a divisão de 2*PI radianos e o número de lados deste polígono.
Em seguida, é feito um laço que produz linhas que conectam os vértices do polígono. Para a coordenada X é considerado o cosseno do ângulo e para a coordenada Y é considerado o seno do ângulo.
O código comentado pode ser visto abaixo.
//raio da circunferência
int raio = 200;
//número de lados do polígono
int lados = 6;
void setup(){
size(600,600);
//ângulo do lado interno do polígono
float ang = 2*PI/lados;
/*circunferência que serve de base, retire o comentário
para ver a circunferência ao executar o código*/
//ellipse(width/2,height/2,2*raio,2*raio);
//cálculo do local que fica cada vértice do polígono
for (int i =0;i<lados;i++){
line(width/2+raio*cos(i*ang),height/2 + raio*sin(i*ang), width/2 + raio*cos((i+1)*ang),height/2 + raio*sin((i+1)*ang));
}
}
terça-feira, 26 de janeiro de 2016
Média, Desvio Padrão e Eistein
Na aula sobre média e desvio padrão, analisamos a média dos tons de cinza da famosa imagem de Albert Eistein, também aplicando sobre a análise desta média os desvios padrões.
Na atividade passada para ser feita em casa, foi pedido que fossem analisadas essa mesma imagem com variações de brilho e contraste.
Primeiro, vou deixar aqui o código comentado utilizado para isso.
//variável que armazena a imagem
PImage img;
void setup(){
size(640, 480);
float t=0, mediaT, somaT=0;
int pos;
//carregamento da imagem
img = loadImage("einstein.jpg");
//a imagem é percorrida e são pegues os valores vermelhos dos pixels
for (int x = 0; x < 640; x++){
for (int y = 0 ; y < 480; y++){
pos = y * 640 + x;
t = red(img.pixels[pos]);
//aqui, são deixados o valores totais somados destes pixels
somaT = somaT + t;
}
}
//aqui, é calculada a média destes valores
mediaT = somaT/(640*480);
println("Média de Tons é ", mediaT);
/*aqui, é calculado o desvio padrão a partir da raiz quadrada da variância (armazenada
na variável "v"*/
float v, SomaV = 0;
for (int x = 0; x < 640; x++){
for (int y = 0; y < 480; y++){
pos = y * 640 + x;
t = red(img.pixels[pos]);
v = pow(t - mediaT, 2);
SomaV = SomaV + sqrt(v);
}
}
//desvio padrão
float media = SomaV/(640*480);
println(media);
}
void draw(){
image(img, 0, 0);
}
Nas imagens com níveis diferentes de brilho e contraste havia uma alteração significativa nos valores da média e desvio padrão. Quanto maior o brilho, maior o desvio padrão, o que é refletido pelo maior valor que um brilho maior dá para os pixels que compõem a imagem.
Na atividade passada para ser feita em casa, foi pedido que fossem analisadas essa mesma imagem com variações de brilho e contraste.
Primeiro, vou deixar aqui o código comentado utilizado para isso.
//variável que armazena a imagem
PImage img;
void setup(){
size(640, 480);
float t=0, mediaT, somaT=0;
int pos;
//carregamento da imagem
img = loadImage("einstein.jpg");
//a imagem é percorrida e são pegues os valores vermelhos dos pixels
for (int x = 0; x < 640; x++){
for (int y = 0 ; y < 480; y++){
pos = y * 640 + x;
t = red(img.pixels[pos]);
//aqui, são deixados o valores totais somados destes pixels
somaT = somaT + t;
}
}
//aqui, é calculada a média destes valores
mediaT = somaT/(640*480);
println("Média de Tons é ", mediaT);
/*aqui, é calculado o desvio padrão a partir da raiz quadrada da variância (armazenada
na variável "v"*/
float v, SomaV = 0;
for (int x = 0; x < 640; x++){
for (int y = 0; y < 480; y++){
pos = y * 640 + x;
t = red(img.pixels[pos]);
v = pow(t - mediaT, 2);
SomaV = SomaV + sqrt(v);
}
}
//desvio padrão
float media = SomaV/(640*480);
println(media);
}
void draw(){
image(img, 0, 0);
}
Nas imagens com níveis diferentes de brilho e contraste havia uma alteração significativa nos valores da média e desvio padrão. Quanto maior o brilho, maior o desvio padrão, o que é refletido pelo maior valor que um brilho maior dá para os pixels que compõem a imagem.
Barco Seno
A função seno consiste na projeção do deslocamento de um ponto no eixo y do gráfico, variando de -1 a 1. Um exemplo disso pode ser verificado no gif abaixo:
Na atividade relativa a essa aula, foi pedido a turma que fosse feita uma aplicação no processing que consistisse de um barco navegando no mar e seu movimento fosse correspondente a função seno.
Segue abaixo o código comentado com um gif ilustrando o resultado:
/*variáveis que armazenam as imagens do barco, do céu(metade de cima da imagem
e do mar(metade de baixo da imagem)*/
PImage barquinho, ceu, mar;
void setup(){
size(800, 600);
barquinho = loadImage("barquinho.png");
ceu = loadImage("ceu.png");
mar = loadImage("mar.png");
noStroke();
}
float x = 0;
void draw(){
background(255);
//eixo y irá pegar o seno do eixo x, causando a variação na altura do barco
float y = sin(x);
//o eixo x será incrementado, para haver o deslocamento horizontal do barco
x+= 0.1;
//para ficar mais aparente, o eixo y tem seu valor multiplicado em 10 vezes
y = y*10;
image(ceu, 0, 0);
/*o barco tem o deslocamento aumentado em 30 vezes no eixo horizontal para
dar a impressão de ter uma navegação no mar de forma mais "realista", enquanto que
o eixo y foi adicionado em 90 para que ele fique num ponto que seja mais coerente
com a imagem*/
image(barquinho, x*30, y+90);
image(mar, 0, 300);
}
Na atividade relativa a essa aula, foi pedido a turma que fosse feita uma aplicação no processing que consistisse de um barco navegando no mar e seu movimento fosse correspondente a função seno.
Segue abaixo o código comentado com um gif ilustrando o resultado:
/*variáveis que armazenam as imagens do barco, do céu(metade de cima da imagem
e do mar(metade de baixo da imagem)*/
PImage barquinho, ceu, mar;
void setup(){
size(800, 600);
barquinho = loadImage("barquinho.png");
ceu = loadImage("ceu.png");
mar = loadImage("mar.png");
noStroke();
}
float x = 0;
void draw(){
background(255);
//eixo y irá pegar o seno do eixo x, causando a variação na altura do barco
float y = sin(x);
//o eixo x será incrementado, para haver o deslocamento horizontal do barco
x+= 0.1;
//para ficar mais aparente, o eixo y tem seu valor multiplicado em 10 vezes
y = y*10;
image(ceu, 0, 0);
/*o barco tem o deslocamento aumentado em 30 vezes no eixo horizontal para
dar a impressão de ter uma navegação no mar de forma mais "realista", enquanto que
o eixo y foi adicionado em 90 para que ele fique num ponto que seja mais coerente
com a imagem*/
image(barquinho, x*30, y+90);
image(mar, 0, 300);
}
A importância dos conjuntos nas aplicações
A teoria dos conjuntos ajuda principalmente na organização do raciocínio crítico e no desenvolvimento de métodos que solucionem problemas. Por exemplo, na aula do dia 15/02, foi passado uma atividade que consistia de aplicarmos de forma contínua mais e mais filtros e ruídos a uma image, finalmente colocando-a em uma moldura.
Isso foi a aplicação da teoria dos conjuntos, em que uma propriedade era aplicada sobre a outra, adicionando a anterior e obtendo um resultado que só era possível com a junção da aplicação dos dois métodos. É uma clássica representação da propriedade de um conjunto estar contido no outro, no caso, de uma propriedade estar contida em outra.
Ajuste de contraste
O ajuste de contraste numa imagem é feito a partir da alteração dos valores RGB desta imagem. Quanto maior for o valor dado aos parâmetros RGB, a imagem será mais clara, assim como quanto menores forem estes valores ela vai se tornando mais escura.
Segue abaixo o código que fiz junto com os comentários explicando cada parte do código. Ao final, uma imagem demonstrando o resultado.
//variável com a imagem original
PImage imgOriginal;
//variável que irá armazenar a cópia da imagem, informando o tamanho dele
PImage imgCopia = createImage(320, 240, RGB);
//variável que referencia a posição dos pixels
int pos;
/*variáveis que armazenam o valor dos pixels referenciando, respectivamente,
red, green e blue*/
float r;
float g;
float b;
//variável que receberá o valor de contraste
float contraste;
void setup(){
size(640, 480);
imgOriginal = loadImage("original.jpg");
//loop que percorrerá a imagem original
for (int x = 0; x < 320; x++){
for (int y = 0; y <240; y++){
pos = y * 320 + x;
//valor dado ao contraste que irá modificar a imagem
contraste = 30;
//armazenamento do valor RGB dos pixels da imagem original somados ao contraste
r = contraste + red(imgOriginal.pixels[pos]);
g = contraste + green(imgOriginal.pixels[pos]);
b = contraste + blue(imgOriginal.pixels[pos]);
//imagem recebe os valores RGB somado com o contraste
imgCopia.pixels[pos] = color(r, g, b);
}
}
}
void draw(){
//posicionamento das imagens
image(imgOriginal, 0, 0);
image(imgCopia, 320, 0);
}
Segue abaixo o código que fiz junto com os comentários explicando cada parte do código. Ao final, uma imagem demonstrando o resultado.
//variável com a imagem original
PImage imgOriginal;
//variável que irá armazenar a cópia da imagem, informando o tamanho dele
PImage imgCopia = createImage(320, 240, RGB);
//variável que referencia a posição dos pixels
int pos;
/*variáveis que armazenam o valor dos pixels referenciando, respectivamente,
red, green e blue*/
float r;
float g;
float b;
//variável que receberá o valor de contraste
float contraste;
void setup(){
size(640, 480);
imgOriginal = loadImage("original.jpg");
//loop que percorrerá a imagem original
for (int x = 0; x < 320; x++){
for (int y = 0; y <240; y++){
pos = y * 320 + x;
//valor dado ao contraste que irá modificar a imagem
contraste = 30;
//armazenamento do valor RGB dos pixels da imagem original somados ao contraste
r = contraste + red(imgOriginal.pixels[pos]);
g = contraste + green(imgOriginal.pixels[pos]);
b = contraste + blue(imgOriginal.pixels[pos]);
//imagem recebe os valores RGB somado com o contraste
imgCopia.pixels[pos] = color(r, g, b);
}
}
}
void draw(){
//posicionamento das imagens
image(imgOriginal, 0, 0);
image(imgCopia, 320, 0);
}
Criação de um mapa com tileset isométrico
Na construção do mapa de um jogo, precisamos nos questionar como ele será apresentado na tela, levando sempre em consideração a dimensão dos tiles (ou seja, as imagens) que o compõem.
Para o exercício da aula sobre conjuntos, foi construído com a ajuda de uma matriz uma imagem com diferentes tilesets. Dependendo do valor que havia na matriz, era carregada uma imagem diferente.
Para o exercício passado para casa, foi pedido que construíssemos no Processing uma imagem utilizando um tileset isométrico.
Abaixo, segue o código comentado explicando cada parte dele e em seguida a imagem resultante.
//variáveis que irão armazenar as imagens utilizadas nesta atividade
PImage imgroadNorth, imgroadSouth, imgroadWest, imgroadEast;
//montagem da matriz que irá inserir os elementos da imagem
int[][]mapa = {{2,2,2,2,2,2,2,2},
{3,1,0,1,0,0,1,0},
{0,2,0,0,0,1,3,0},
{0,3,0,2,1,0,0,0},
{0,2,0,3,0,0,1,0},
{0,0,1,2,0,2,0,0},
{0,1,0,2,0,2,1,0},
{1,1,1,1,1,1,1,1}};
void setup(){
size(800, 420);
}
void draw(){
//arquivos usados: olhe o nome depois de "img"
//tamanho das imagens: 100 x 65
imgroadNorth = loadImage("roadNorth.png");
imgroadSouth= loadImage("roadTSouth.png");
imgroadWest= loadImage("roadTWest.png");
imgroadEast = loadImage("roadEast.png");
//para fazer a imagem, foi feito um laço dentro de outro laço que percorrem a matriz
//a matriz é percorrida de coluna em coluna de forma sequencial.
//Terminada uma coluna, é passado para a próxima.
for(int i=0; i<8; i++){
for(int j=0; j<8; j++){
/*ao percorrer a matriz, é considerado a numeração de cada índice
para que sejam escolhidas as imagens que serão desenhadas na tela*/
switch(mapa[j][i]){
case 0:
/*para a localização de cada imagem, foi considerado tanto o formato da figura que
ela possui quanto suas dimensões, além das dimensões da tela.
Além disso, era necessário considerar o posicionamento da próxima figura
na tela. Para cada elemento, ele soma na posição Y um quarto da altura
da imagem e na posição X ele diminui um quarto da largura da imagem.
Claro, isto funciona nas dimensões destas imagens.
*/
image(imgroadNorth, i*50-j*50+width/2-50, j*25+i*25);
break;
case 1:
image(imgroadSouth, i*50-j*50+width/2-50, j*25+i*25);
break;
case 2:
image(imgroadWest, i*50-j*50+width/2-50, j*25+i*25);
break;
case 3:
image(imgroadEast, i*50-j*50+width/2-50, j*25+i*25);
break;
}
}
}
}
Para o exercício da aula sobre conjuntos, foi construído com a ajuda de uma matriz uma imagem com diferentes tilesets. Dependendo do valor que havia na matriz, era carregada uma imagem diferente.
Para o exercício passado para casa, foi pedido que construíssemos no Processing uma imagem utilizando um tileset isométrico.
Abaixo, segue o código comentado explicando cada parte dele e em seguida a imagem resultante.
//variáveis que irão armazenar as imagens utilizadas nesta atividade
PImage imgroadNorth, imgroadSouth, imgroadWest, imgroadEast;
//montagem da matriz que irá inserir os elementos da imagem
int[][]mapa = {{2,2,2,2,2,2,2,2},
{3,1,0,1,0,0,1,0},
{0,2,0,0,0,1,3,0},
{0,3,0,2,1,0,0,0},
{0,2,0,3,0,0,1,0},
{0,0,1,2,0,2,0,0},
{0,1,0,2,0,2,1,0},
{1,1,1,1,1,1,1,1}};
void setup(){
size(800, 420);
}
void draw(){
//arquivos usados: olhe o nome depois de "img"
//tamanho das imagens: 100 x 65
imgroadNorth = loadImage("roadNorth.png");
imgroadSouth= loadImage("roadTSouth.png");
imgroadWest= loadImage("roadTWest.png");
imgroadEast = loadImage("roadEast.png");
//para fazer a imagem, foi feito um laço dentro de outro laço que percorrem a matriz
//a matriz é percorrida de coluna em coluna de forma sequencial.
//Terminada uma coluna, é passado para a próxima.
for(int i=0; i<8; i++){
for(int j=0; j<8; j++){
/*ao percorrer a matriz, é considerado a numeração de cada índice
para que sejam escolhidas as imagens que serão desenhadas na tela*/
switch(mapa[j][i]){
case 0:
/*para a localização de cada imagem, foi considerado tanto o formato da figura que
ela possui quanto suas dimensões, além das dimensões da tela.
Além disso, era necessário considerar o posicionamento da próxima figura
na tela. Para cada elemento, ele soma na posição Y um quarto da altura
da imagem e na posição X ele diminui um quarto da largura da imagem.
Claro, isto funciona nas dimensões destas imagens.
*/
image(imgroadNorth, i*50-j*50+width/2-50, j*25+i*25);
break;
case 1:
image(imgroadSouth, i*50-j*50+width/2-50, j*25+i*25);
break;
case 2:
image(imgroadWest, i*50-j*50+width/2-50, j*25+i*25);
break;
case 3:
image(imgroadEast, i*50-j*50+width/2-50, j*25+i*25);
break;
}
}
}
}
domingo, 24 de janeiro de 2016
TED Talk: A Beleza na visualização dos dados
TED Talks costumam ser pequenas palestras que tentam ser concisas e buscam sempre mostrar um ponto de vista diferenciado com seus palestrantes. Não por coincidência, somos surpreendidos pela bela palestra de David McCandless com sua demonstração sobre a importância da forma que visualizamos os dados de qualquer pesquisa.
Números, por si só, não colaboram na demonstração realista dos fatos que eles representam. Dizer que uma crise econômica irá prejudicar no desenvolvimento da maioria dos países é uma coisa, entretanto no momento que ele demonstrou graficamente que todo o prejuízo causado por esta crise engoliria facilmente todas as riquezas produzidas por vários países desenvolvidos no curso de um ano, o impacto dessa visualização é sentido na platéia.
A utilização de gráficos facilita a compreensão do dado bruto, o qual quando apenas colocado em uma tabela não deixa fácil sua leitura ou sua compreensão. Outro exemplo, demonstrado pelo palestrante é como fica mais fácil encontrar uma vitamina que ele toma como suplemento se ele se utilizar não apenas de uma demonstração visual dos dados que ele possui, mas aplicar também uma interatividade com a aplicação que está demonstrando aquele dado, destacando de forma dinâmica exatamente o que ele mais precisa.
Na realidade, a percepção da importância da utilização de representação gráfica de dados tem sido algo que tem aumentado bastante. Por exemplo, existe um subreddit (que é uma comunidade dentro do site de compartilhamento de links chamado reddit) chamado Data is Beautiful, o qual consiste de mostrar diferentes representações gráficas que demonstram desde que pessoas que trabalham em casa durante tempestades de neve produzem mais até demonstrar a correlação dos gastos nos Estados Unidos em ciência, viagem espacial e tecnologia com suicídios por enforcamento, estrangulamento e sufocamento.
sábado, 28 de novembro de 2015
Trabalho: Parte I
Artista escolhido: Luiz Sacliotto
Obra escolhida: Concreção 9768
Análise geométrica
A obra que escolhi para analisar geometricamente e basear meu trabalho foi a concreção 9768 do artista abstracionista Luiz Sacliotto.
Para o preenchimento de cada quadrado, antes do laço iniciar uso a função fill do Processing para preencher o quadrado maior. Depois disso, faço uma condicional para que a cada repetição par, o quadrado seja preenchido por uma coloração vermelha.
Feito isto, para a segunda parte, precisamos que a coordenada inicial "x" tenha o valor do quadrado maior para que a próxima parte tenha sua formação iniciada ao lado da parte anterior sem sobrepô-la. Além disso, a cada repetição do laço, tanto a coordenada x quanto a y na função rect terão seus valores respectivamente somados e diminuídos por "h", para que os quadrados seguintes sejam feitos na mesma proporção que a parte anterior.
Para o preenchimento, é invertida a ordem que foi feita os preenchimentos da parte anterior.
Tomando este cuidado com todas as partes, temos finalmente a reprodução da obra:
Apropriação
Feita a replicação da obra, resolvi colocar a função dentro de um laço e a cada repetição do laço a totalidade da obra feita anteriormente se tornaria a primeira parte de uma obra ainda maior.
Segue abaixo todo o meu código completo para executar esta última etapa.
void setup(){
background(255);
size(1920, 1080);
}
void luizSacliotto(int h, int posX, int posY){
int c = h * 4;
fill(0);
//primeira parte
for(int i = 0; i<=3 ; i++){
rect(posX, posY, c, c);
posY += h;
c = c - h;
if(i%2==0){
fill(125,0 , 0);
}else{
fill(0);
}
}
//segunda parte
c= 4*h;
posX = c;
posY = 0;
fill(125,0,0);
for(int j = 0; j<=3; j++){
rect(posX, posY, c, c);
posY +=h;
posX += h;
c = c - h;
if(j%2==0){
fill(0);
}else{
fill(125,0,0);
}
}
//terceira parte
c = 4*h;
posX = 0;
posY = c;
fill(125,0,0);
for(int k = 0; k<=3; k++){
rect(posX, posY, c, c);
c -=h;
if(k%2==0){
fill(0);
}else{
fill(125, 0, 0);
}
}
//quarta parte
c= 4*h;
posX = c;
posY = c;
fill(0);
for(int m = 0; m<=3; m++){
rect(posX, posY, c, c);
posX +=h;
posY +=h;
c -=h;
if(m%2==0){
fill(125,0,0);
}else{
fill(0);
}
}
}
void draw(){
int localX = 0;
int localY = 0;
int tamanho = 40;
for(int j=0; j<=4; j++){
luizSacliotto(tamanho, localX, localY);
localX += 8*tamanho;
tamanho+= tamanho;
}
}
Obra escolhida: Concreção 9768
Análise geométrica
A obra que escolhi para analisar geometricamente e basear meu trabalho foi a concreção 9768 do artista abstracionista Luiz Sacliotto.
Pela análise geométrica da obra do artista, pode perceber o padrão do distanciamento entre cada um dos quadrados, o qual ocorria sempre a uma distância fixa. Se considerarmos cada cor de preenchimento como pertencente a um quadrado de tamanho diferente, é possível construir um programa que se faça valer destas propriedades.
Programação
Primeiramente, dividi a obra em quatro partes, para melhor programar seu preenchimento.
Utilizando a função rect do Processing, fiz uma função chamada luizSacliotto que recebe 3 inputs: o tamanho que terão os quadrados menores e as coordenadas "x" e "y" na qual será iniciada a construção da obra. Como o quadrado maior de uma parte tem 4 vezes o tamanho do lado do quadrado menor, uma variável chamada "c" é criada para guardar este valor.
Em seguida, coloquei esta função dentro de um laço que decrementa a cada repetição o valor de "c" em "h", construindo assim quadrados menores. Além disso, a coordenada y tinha seu valor somado em "h" para que o próximo quadrado fosse construído a uma distância que fosse igual ao lado do menor quadrado.
Feito isso, está completa a primeira parte da obra.
Para o preenchimento, é invertida a ordem que foi feita os preenchimentos da parte anterior.
Tomando este cuidado com todas as partes, temos finalmente a reprodução da obra:
Apropriação
Feita a replicação da obra, resolvi colocar a função dentro de um laço e a cada repetição do laço a totalidade da obra feita anteriormente se tornaria a primeira parte de uma obra ainda maior.
Segue abaixo todo o meu código completo para executar esta última etapa.
void setup(){
background(255);
size(1920, 1080);
}
void luizSacliotto(int h, int posX, int posY){
int c = h * 4;
fill(0);
//primeira parte
for(int i = 0; i<=3 ; i++){
rect(posX, posY, c, c);
posY += h;
c = c - h;
if(i%2==0){
fill(125,0 , 0);
}else{
fill(0);
}
}
//segunda parte
c= 4*h;
posX = c;
posY = 0;
fill(125,0,0);
for(int j = 0; j<=3; j++){
rect(posX, posY, c, c);
posY +=h;
posX += h;
c = c - h;
if(j%2==0){
fill(0);
}else{
fill(125,0,0);
}
}
//terceira parte
c = 4*h;
posX = 0;
posY = c;
fill(125,0,0);
for(int k = 0; k<=3; k++){
rect(posX, posY, c, c);
c -=h;
if(k%2==0){
fill(0);
}else{
fill(125, 0, 0);
}
}
//quarta parte
c= 4*h;
posX = c;
posY = c;
fill(0);
for(int m = 0; m<=3; m++){
rect(posX, posY, c, c);
posX +=h;
posY +=h;
c -=h;
if(m%2==0){
fill(125,0,0);
}else{
fill(0);
}
}
}
void draw(){
int localX = 0;
int localY = 0;
int tamanho = 40;
for(int j=0; j<=4; j++){
luizSacliotto(tamanho, localX, localY);
localX += 8*tamanho;
tamanho+= tamanho;
}
}
segunda-feira, 23 de novembro de 2015
As facilidades das funções
Na nossa aula do dia 19/11/2015, foi passado para nós a seguinte atividade em sala de aula: fazer uma barra de slider no Processing.
Uma barra de slider é algo que vemos comumente em interfaces que querem dar várias opções em um menu. Por exemplo, para deixarmos o nível do volume de um som num nível agradável, normalmente representamos a intensidade do som reproduzido através de uma barra de slider.
Para este exercício, produzi o código abaixo. Para dar um efeito visual mais interessante, fiz com que o quadrado deste slider se desloque continuamente entre as extremidades:
float x;
float d = 0.01;
void setup(){
size(600, 600);
}
//função do quadrado menor
void slideBar(float p){ //pega um valor que vai mexer o quadrado
fill(255);
rect(25, 20, 550, 100);
float whatever; //este será o valor que vai ser a coordenada X
whatever = 25+450*p; //25(distancia da borda da janela) + 450(tamanho do retângulo maior - lado do quadrado) * p(a proporção que vai ser o input da função
fill(125);
rect(whatever, 20, 100,100);
}
void draw(){
background(0);
x = x + d;
if(x >= 1 || x <=0){
d = -d;
}
slideBar(x);
}
Como podemos ver no código para facilitar meu trabalho eu resolvi compartimentar grande parte dele dentro de uma função.
Funções são ferramentas importantes na programação, permitindo que certas partes do código sejam compartimentadas em diferentes porções, sendo chamadas apenas quando necessário. Além disso, posso utilizá-los várias vezes dentro do mesmo bloco de código, o que o torna até mesmo mais legível.
Além disso, o código quando é reservado para uma função torna sua alteração mais rápida e fácil. Se eu preciso modificar alguma coisa, basta modificar dentro da função que essa alteração será aplicada em todas as instâncias que ela for chamada.
Em resumo, a utilização de funções dinamiza e facilita a compreensão não apenas do código, mas da lógica da programação empregada na construção do mesmo.
Uma barra de slider é algo que vemos comumente em interfaces que querem dar várias opções em um menu. Por exemplo, para deixarmos o nível do volume de um som num nível agradável, normalmente representamos a intensidade do som reproduzido através de uma barra de slider.
Para este exercício, produzi o código abaixo. Para dar um efeito visual mais interessante, fiz com que o quadrado deste slider se desloque continuamente entre as extremidades:
float x;
float d = 0.01;
void setup(){
size(600, 600);
}
//função do quadrado menor
void slideBar(float p){ //pega um valor que vai mexer o quadrado
fill(255);
rect(25, 20, 550, 100);
float whatever; //este será o valor que vai ser a coordenada X
whatever = 25+450*p; //25(distancia da borda da janela) + 450(tamanho do retângulo maior - lado do quadrado) * p(a proporção que vai ser o input da função
fill(125);
rect(whatever, 20, 100,100);
}
void draw(){
background(0);
x = x + d;
if(x >= 1 || x <=0){
d = -d;
}
slideBar(x);
}
Como podemos ver no código para facilitar meu trabalho eu resolvi compartimentar grande parte dele dentro de uma função.
Funções são ferramentas importantes na programação, permitindo que certas partes do código sejam compartimentadas em diferentes porções, sendo chamadas apenas quando necessário. Além disso, posso utilizá-los várias vezes dentro do mesmo bloco de código, o que o torna até mesmo mais legível.
Além disso, o código quando é reservado para uma função torna sua alteração mais rápida e fácil. Se eu preciso modificar alguma coisa, basta modificar dentro da função que essa alteração será aplicada em todas as instâncias que ela for chamada.
Em resumo, a utilização de funções dinamiza e facilita a compreensão não apenas do código, mas da lógica da programação empregada na construção do mesmo.
Bolas que se colorem com a seta do mouse
Dentre as atividades que foram passadas para serem feitas em casa e postadas aqui neste blog, foi pedido que fizéssemos um programa no Processing que produzisse em locais aleatórios duas circunferências, também com raios aleatórios.
Quando a seta do mouse passasse sobre elas, estas circunferências devem mudar de cor e quando a seta do mouse sair de cima delas, elas devem deixar de ter essa cor.
Para facilitar meu trabalho, reaproveitei o código de uma outra atividade feita em sala que calcula a distância entre dois pontos, apenas adicionando novas variáveis que tem seu valor gerado randomicamente a cada vez que o programa é aberto e chamando as funções apenas para mudar a cor das circunferências dentro da condição estabelecida (mouse dentro da circunferência). Segue o código explicado através de comentários abaixo.
float xBola1;
float yBola1;
float xBola2;
float yBola2;
float raio1;
float raio2;
//cálculo da distância entre dois pontos na mesma linha
float distancia1D(float X1, float X2){
float resposta;
resposta = X2 - X1;
return sqrt(pow(resposta, 2));
}
//cálculo da distância entre dois pontos em qualquer lugar na tela
float distancia2D(float x1, float y1, float x2, float y2){
float coordenadaX;
coordenadaX = distancia1D(x2, x1);
float coordenadaY;
coordenadaY = distancia1D(y2, y1);
float distancia = round(sqrt(pow(coordenadaX, 2) + pow(coordenadaY, 2)));
return distancia;
}
void setup(){
size(600, 600);
//determinar de forma aleatória a localização e o raio das circunferências
xBola1 = round(random(width));
yBola1 = round(random(height));
xBola2 = round(random(width));
yBola2 = round(random(height));
raio1 = round(random(20, 80));
raio2 = round(random(20, 80));
}
void draw(){
background(0);
//colocamos a condicional para colorir a bola caso o mouse entre nela
if(distancia2D(mouseX, mouseY, xBola1, yBola1) <= raio1){
fill(125);
}
//fazemos a primeira ellipse dando como parâmetros sua localização e o raio gerado
ellipse(xBola1, yBola1, raio1*2, raio1*2);
//ao afastar a seta do mouse, volta a ficar branca
fill(255);
//faz o mesmo com a outra circunferencia
if(distancia2D(mouseX, mouseY, xBola2, yBola2) <=raio2){
fill(0, 123, 200);
}
ellipse(xBola2, yBola2, raio2*2, raio2*2);
fill(255);
}
Quando a seta do mouse passasse sobre elas, estas circunferências devem mudar de cor e quando a seta do mouse sair de cima delas, elas devem deixar de ter essa cor.
Para facilitar meu trabalho, reaproveitei o código de uma outra atividade feita em sala que calcula a distância entre dois pontos, apenas adicionando novas variáveis que tem seu valor gerado randomicamente a cada vez que o programa é aberto e chamando as funções apenas para mudar a cor das circunferências dentro da condição estabelecida (mouse dentro da circunferência). Segue o código explicado através de comentários abaixo.
float xBola1;
float yBola1;
float xBola2;
float yBola2;
float raio1;
float raio2;
//cálculo da distância entre dois pontos na mesma linha
float distancia1D(float X1, float X2){
float resposta;
resposta = X2 - X1;
return sqrt(pow(resposta, 2));
}
//cálculo da distância entre dois pontos em qualquer lugar na tela
float distancia2D(float x1, float y1, float x2, float y2){
float coordenadaX;
coordenadaX = distancia1D(x2, x1);
float coordenadaY;
coordenadaY = distancia1D(y2, y1);
float distancia = round(sqrt(pow(coordenadaX, 2) + pow(coordenadaY, 2)));
return distancia;
}
void setup(){
size(600, 600);
//determinar de forma aleatória a localização e o raio das circunferências
xBola1 = round(random(width));
yBola1 = round(random(height));
xBola2 = round(random(width));
yBola2 = round(random(height));
raio1 = round(random(20, 80));
raio2 = round(random(20, 80));
}
void draw(){
background(0);
//colocamos a condicional para colorir a bola caso o mouse entre nela
if(distancia2D(mouseX, mouseY, xBola1, yBola1) <= raio1){
fill(125);
}
//fazemos a primeira ellipse dando como parâmetros sua localização e o raio gerado
ellipse(xBola1, yBola1, raio1*2, raio1*2);
//ao afastar a seta do mouse, volta a ficar branca
fill(255);
//faz o mesmo com a outra circunferencia
if(distancia2D(mouseX, mouseY, xBola2, yBola2) <=raio2){
fill(0, 123, 200);
}
ellipse(xBola2, yBola2, raio2*2, raio2*2);
fill(255);
}
domingo, 22 de novembro de 2015
Exemplo do Processing
Na nossa segunda aula, foi pedido que fosse pegue um dos exemplos presentes no site https://processing.org/examples , analisássemos algum que nos chamasse a atenção e o modificasse para ter algum tipo de efeito diferenciado.
Dentre os exemplos, um dos que mais me chamaram a atenção foi este simples código em que eram criados algumas elipses que seguiam a seta do mouse.
Dentre os exemplos, um dos que mais me chamaram a atenção foi este simples código em que eram criados algumas elipses que seguiam a seta do mouse.
Segue o código desse exemplo abaixo:
float x = 100;
float y = 100;
float angle1 = 0.0;
float segLength = 50;
void setup() {
size(640, 360);
strokeWeight(20.0);
stroke(255, 100);
}
void draw() {
background(0);
float dx = mouseX - x;
float dy = mouseY - y;
angle1 = atan2(dy, dx);
x = mouseX - (cos(angle1) * segLength);
y = mouseY - (sin(angle1) * segLength);
segment(x, y, angle1);
ellipse(x, y, 20, 20);
}
void segment(float x, float y, float a) {
pushMatrix();
translate(x, y);
rotate(a);
line(0, 0, segLength, 0);
popMatrix();
}
Para efeitos de exemplo, resolvi fazer com que no lugar das elipses tivessem retângulos e a cor deste objeto fosse mudando dependendo do local que se encontrava o mouse na tela. Para ter o efeito desejado, precisei retirar a função stroke de dentro da função setup e deixá-la na função draw, para que a cor do objeto fosse mudando a cada novo frame.
Segue o código editado abaixo:
float x = 100;
float y = 100;
float angle1 = 0.0;
float segLength = 50;
void setup() {
size(640, 360);
strokeWeight(20.0);
}
void draw() {
background(0);
stroke(mouseX, 100, mouseY);
float dx = mouseX - x;
float dy = mouseY - y;
angle1 = atan2(dy, dx);
x = mouseX - (cos(angle1) * segLength);
y = mouseY - (sin(angle1) * segLength);
segment(x, y, angle1);
rect(x, y, 20, 20);
}
void segment(float x, float y, float a) {
pushMatrix();
translate(x, y);
rotate(a);
line(0, 0, segLength, 0);
popMatrix();
}
quinta-feira, 19 de novembro de 2015
Bolinha acelerando e se batendo
Dentre as atividades que foram passadas, foi determinado que fosse produzida uma circunferência que se deslocaria tanto horizontalmente quanto verticalmente pela tela e, quando ela encostasse nos cantos da janela, sua velocidade fosse aumentada em 1%.
Segue abaixo o código com os comentários explicando como ele foi produzido.
//determinação dos valores das variáveis
float bolaX = 10;
float bolaY = 15;
float dX = 15;
float dY = 15;
float acelerador = 0.01;
//tamanho da tela
void setup(){
size(800, 600);
}
void draw(){
background(0);
//bola tem sua posição determinada
ellipse(bolaX, bolaY, 40, 40);
//deslocamento da bola
bolaX = bolaX + dX;
bolaY = bolaY + dY;
/*a cada vez que a bola encostar numa parede, ela terá uma mudança na sua tranjetória
e sua velocidade vai ser aumentada em 1% */
if(bolaX>=790){
dX = -(dX +dX*acelerador);
}
else if(bolaX <10){
dX = -(dX +dX*acelerador);
}
else if(bolaY>=590){
dY = -(dY+dY*acelerador);
}
else if(bolaY<10){
dY = -(dY+dY*acelerador);
}
}
Pong!
Na atividade para casa da aula 10, foi pedido que fizéssemos no Processing um jogo parecido com o clássico jogo Pong, o qual foi um dos primeiros a serem desenvolvidos e foi um dos maiores responsáveis tanto da popularização dos arcades e que tornaram possível o nascimento dos videogames.
Segue abaixo o código com comentários explicando cada parte principal dele. Em seguida, um gif demonstrando o jogo funcionando.
Para este jogo, eu reaproveitei o código de uma outra atividade que foi feita anteriormente em sala de aula que consistia em fazer uma bolinha se mover livremente pela tela e quando se chocasse com os limites da janela ela mudaria de direção.
Tive alguns problemas na determinação da colisão com os paddles, mas ainda assim gostei bastante do resultado.
//coordenadas iniciais da bola
int bolaX = 100;
int bolaY = 150;
//modificadores da trajetória da bola
int dX = 5;
int dY = 5;
//coordenadas iniciais do primeiro paddle
int xP1 = 20;
int yP1 = 120;
//coordenadas iniciais do segundo paddle
int xP2 = 280;
int yP2 = 120;
//raio da bolinha
int raio = 20;
void setup(){
size(320, 240);
}
void draw(){
background(0);
mover();
//aqui é feita a bolinha
ellipse(bolaX, bolaY, raio*2, raio*2);
//aqui são feitos os paddles
rect(xP1, yP1, 20, 80);
rect(xP2, yP2, 20, 80);
//nesta parte, temos a determinação do deslocamento da bola de forma costante, sendo um MRU
bolaX = bolaX + dX;
bolaY = bolaY + dY;
//mudança da direção da bola ao tocar nas bordas
if(bolaX>=300){
dX = -dX;
}
else if(bolaX <10){
dX = -dX;
}
else if(bolaY>=220){
dY = -dY;
}
else if(bolaY<10){
dY = -dY;
}
//mudança na direção da bola ao tocar um dos paddles
if(Colisao(xP1, yP2) || Colisao(xP2, yP2)){
dX = -dX;
dY = -dY;
}
//finalização do jogo quando a bola toca uma das bordas da janela do jogo
if(bolaX > (width-raio)){
gameOver(true);
}
else if(bolaX< raio){
gameOver(false);
}
}
/*função que determina o comportamento da bola quando colidir
com um dos paddles*/
boolean Colisao(int xP, int yP){
if(bolaY >= yP - raio && bolaY <= yP+ 80+raio){
if(bolaX >= xP - raio && bolaX <= xP + 20 + raio){
return true;
}
else
return false;
}
else
return false;
}
//função que movimenta os paddles
void mover(){
if(keyPressed){
if (keyCode == DOWN) {
yP1+=5;
}else if(keyCode == UP){
yP1-=5;
}else if(keyCode == LEFT){
yP2+=5;
}else if(keyCode == RIGHT){
yP2-=5;
}
}
}
//função que termina o jogo, posicionando um texto dizendo qual lado venceu
void gameOver(boolean fimdejogo){
if (fimdejogo){
clear();
text("Esquerda ganhou!", 160, 120);
noLoop();
}
if (!fimdejogo){
clear();
text("Direita ganhou",160,120);
noLoop();
}
}
Segue abaixo o código com comentários explicando cada parte principal dele. Em seguida, um gif demonstrando o jogo funcionando.
Para este jogo, eu reaproveitei o código de uma outra atividade que foi feita anteriormente em sala de aula que consistia em fazer uma bolinha se mover livremente pela tela e quando se chocasse com os limites da janela ela mudaria de direção.
Tive alguns problemas na determinação da colisão com os paddles, mas ainda assim gostei bastante do resultado.
//coordenadas iniciais da bola
int bolaX = 100;
int bolaY = 150;
//modificadores da trajetória da bola
int dX = 5;
int dY = 5;
//coordenadas iniciais do primeiro paddle
int xP1 = 20;
int yP1 = 120;
//coordenadas iniciais do segundo paddle
int xP2 = 280;
int yP2 = 120;
//raio da bolinha
int raio = 20;
void setup(){
size(320, 240);
}
void draw(){
background(0);
mover();
//aqui é feita a bolinha
ellipse(bolaX, bolaY, raio*2, raio*2);
//aqui são feitos os paddles
rect(xP1, yP1, 20, 80);
rect(xP2, yP2, 20, 80);
//nesta parte, temos a determinação do deslocamento da bola de forma costante, sendo um MRU
bolaX = bolaX + dX;
bolaY = bolaY + dY;
//mudança da direção da bola ao tocar nas bordas
if(bolaX>=300){
dX = -dX;
}
else if(bolaX <10){
dX = -dX;
}
else if(bolaY>=220){
dY = -dY;
}
else if(bolaY<10){
dY = -dY;
}
//mudança na direção da bola ao tocar um dos paddles
if(Colisao(xP1, yP2) || Colisao(xP2, yP2)){
dX = -dX;
dY = -dY;
}
//finalização do jogo quando a bola toca uma das bordas da janela do jogo
if(bolaX > (width-raio)){
gameOver(true);
}
else if(bolaX< raio){
gameOver(false);
}
}
/*função que determina o comportamento da bola quando colidir
com um dos paddles*/
boolean Colisao(int xP, int yP){
if(bolaY >= yP - raio && bolaY <= yP+ 80+raio){
if(bolaX >= xP - raio && bolaX <= xP + 20 + raio){
return true;
}
else
return false;
}
else
return false;
}
//função que movimenta os paddles
void mover(){
if(keyPressed){
if (keyCode == DOWN) {
yP1+=5;
}else if(keyCode == UP){
yP1-=5;
}else if(keyCode == LEFT){
yP2+=5;
}else if(keyCode == RIGHT){
yP2-=5;
}
}
}
//função que termina o jogo, posicionando um texto dizendo qual lado venceu
void gameOver(boolean fimdejogo){
if (fimdejogo){
clear();
text("Esquerda ganhou!", 160, 120);
noLoop();
}
if (!fimdejogo){
clear();
text("Direita ganhou",160,120);
noLoop();
}
}
A da BRAUN
Foi pedido como atividade da aula 7 que fizéssemos uma reprodução de parte do logo da empresa BRAUN, uma empresa que teve grande influência na história de design de produtos. Para esta atividade, foi pedido apenas que fosse reproduzido a letra "A" do seu logo, além de que ele ficasse aumentando e diminuindo continuamente.
Abaixo, segue o código com a explicação dele como comentários.
//valores bases dados para as variáveis que sofrerão alterações na execução do código
float aDaBraun = 10;
float aumentador = 5;
void setup(){
size(600,600);
}
void draw(){
background(255);
//chamada da função com a variável estabelecida anteriormente
Braun(aDaBraun);
//adição feita a variável que controla o módulo
aDaBraun= aDaBraun + aumentador;
/*aqui, estabeleço que a variável que modifica a variável
de módulo tenha seu valor invertido a partir do momento
que o módulo passa a ter o tamanho de 50 unidades*/
if(aDaBraun >=50){
aumentador = -aumentador;
}/*aqui, quando o valor passar a ser menor que 10 unidades, o modificador
tem seu valor novamente invertido para que o logo volte a aumentar*/
else if(aDaBraun <=10){
aumentador = -aumentador;
}
}
//função que produz o logo
void Braun(float modulo){
fill(0);
//estabelecimento da posição inicial
float posicaoX = 300+modulo;
float posicaoY = 150+modulo;
noStroke();
//as duas "pernas" do "A"
rect(posicaoX, posicaoY-modulo, modulo, modulo/2);
rect(posicaoX-modulo, posicaoY, modulo, modulo*8);
rect(posicaoX+modulo, posicaoY, modulo, modulo*8);
//curvatura do "A", feita com duas circunferências
ellipse(posicaoX, posicaoY, modulo*2, modulo*2);
ellipse(posicaoX+modulo, posicaoY, modulo*2, modulo*2);
fill(255);
//preenchimento do "A"
rect(posicaoX, posicaoY, modulo, modulo+modulo/2, PI);
fill(0);
//parte de baixo do "A"
rect(posicaoX-modulo, posicaoY+(2.5*modulo), modulo*3, modulo);
}
terça-feira, 27 de outubro de 2015
Bandeira Nacional
Na aula do dia 27/10/2015, foi dado como atividade em sala de aula que fosse produzida através do Processing uma imagem que fosse semelhante a bandeira do Brasil, obedecendo as proporções estabelecidas na lei nº 5.700. Nesta atividade, foi recomendado que fossem produzidos apenas as três formas fundamentais da bandeira: um retângulo, o losango e a circunferência no centro.
As determinações da lei estabeleciam o seguinte para as proporções da bandeira:
Com estas informações, comecei a produzir o retângulo da bandeira. Considerando a distância entre o centro e o lado da mesma, calculei que deveria considerar uma distância x de 10 módulos e uma distância y de 7 módulos para a origem do retângulo.
Em seguida, considerei as distâncias necessárias para ser produzido o losango utilizando a função quad() do Processing. Para cada um dos vértices, calculei a distância que era necessário ele estar tanto do centro da figura enquanto respeitava o limite de deixa-los a 1,7 módulos de distância de cada lado do retângulo.
Finalmente, foi feita a circunferência com raio de 3,5 módulo.
Segue o código abaixo que utilizei, junto com uma imagem demonstrando o código funcionando.
void setup(){
size(800, 600);
}
void mostraBandeiraBrasil(float x, float y, float l){
//determinação do tamanho de cada módulo
float modulo = l/14;
//determinação do raio da circunferência a partir do módulo
float raio = 3.5*modulo;
//retângulo com o preenchimento verde
fill(#00ff00);
rect(x-10*modulo, y-7*modulo, 20*modulo, 14*modulo);
//losango com o preenchimento amarelo
fill(#ffff00);
quad(x - 8.3*modulo, y, x, y-5.3*modulo, x+8.3*modulo, y, x, y+5.3*modulo);
//circunferência com o preenchimento azul
fill(#0000ff);
ellipse(x, y, raio*2, raio*2);
}
void draw(){
mostraBandeiraBrasil( 400, 300, 300);
}
As determinações da lei estabeleciam o seguinte para as proporções da bandeira:
- Para cálculo das dimensões, tomar-se-á por base a largura desejada, dividindo-se esta em 14 (quatorze) partes iguais. Cada uma das partes será considerada uma medida ou módulo.
- O comprimento será de vinte módulos (20M).
- A distância dos vértices do losango amarelo ao quadro externo será de um módulo e sete décimos (1,7M).
- O círculo azul no meio do losango amarelo terá o raio de três módulos e meio (3,5M).
Com estas informações, comecei a produzir o retângulo da bandeira. Considerando a distância entre o centro e o lado da mesma, calculei que deveria considerar uma distância x de 10 módulos e uma distância y de 7 módulos para a origem do retângulo.
Em seguida, considerei as distâncias necessárias para ser produzido o losango utilizando a função quad() do Processing. Para cada um dos vértices, calculei a distância que era necessário ele estar tanto do centro da figura enquanto respeitava o limite de deixa-los a 1,7 módulos de distância de cada lado do retângulo.
Finalmente, foi feita a circunferência com raio de 3,5 módulo.
Segue o código abaixo que utilizei, junto com uma imagem demonstrando o código funcionando.
void setup(){
size(800, 600);
}
void mostraBandeiraBrasil(float x, float y, float l){
//determinação do tamanho de cada módulo
float modulo = l/14;
//determinação do raio da circunferência a partir do módulo
float raio = 3.5*modulo;
//retângulo com o preenchimento verde
fill(#00ff00);
rect(x-10*modulo, y-7*modulo, 20*modulo, 14*modulo);
//losango com o preenchimento amarelo
fill(#ffff00);
quad(x - 8.3*modulo, y, x, y-5.3*modulo, x+8.3*modulo, y, x, y+5.3*modulo);
//circunferência com o preenchimento azul
fill(#0000ff);
ellipse(x, y, raio*2, raio*2);
}
void draw(){
mostraBandeiraBrasil( 400, 300, 300);
}
quinta-feira, 22 de outubro de 2015
Lançamento balístico
Na aula do dia 22/10/2015, foi pedido em sala de aula que fosse produzido um código no Processing que demonstrasse um lançamento balístico como se fosse um lançamento oblíquo.
Um lançamento oblíquo envolve dois tipos de movimento: um movimento retilíneo uniforme (MRU) e um movimento retilíneo uniformemente variado(MRUV), sendo o MRU tem um direcionamento horizontal e o MRUV vertical, causado pela aceleração da gravidade.
Na atividade de hoje, foi pedido que o recálculo do lançamento balístico a cada 0,1 segundo, porém mantendo o tempo real.
Para isto, bastou apenas deixar o Frame Rate no valor de 10(sendo assim a imagem atualizada numa taxa de 10 frames por segundo) e que ao incremento do tempo fosse somado um valor que fosse nesta mesma proporção, como pode ser demonstrado no código abaixo:
void setup(){
frameRate(10);
size(600,600);
}
float tAtual =0;
float aAtual = -10;
int vAtual = 40;
float dEixoX;
float dEixoY;
float soma = float(1)/float(10);
void draw(){
background(255);
mostraGrade();
mostraGradeH();
dEixoX = MRU(float(vAtual), tAtual);
dEixoY = MRUV(vAtual, tAtual, aAtual);
ellipse(dEixoX, 600-dEixoY, 10, 10);
println(tAtual, aAtual, dEixoY, dEixoX);
tAtual = tAtual + soma;
}
float MRUV(float v, float t, float a){
float d;
d = v * t + (a*t*t)/2;
return(d);
}
float MRU(float v, float t){
float d;
d = v * t;
return(d);
}
void mostraGrade(){
for (int i=0; i<12; i++){
line(i*50, 0, i*50, 600);
}
}
void mostraGradeH(){
for(int i=0; i<12; i++){
line(0, i*50, 600, i*50);
}
}
Um lançamento oblíquo envolve dois tipos de movimento: um movimento retilíneo uniforme (MRU) e um movimento retilíneo uniformemente variado(MRUV), sendo o MRU tem um direcionamento horizontal e o MRUV vertical, causado pela aceleração da gravidade.
Na atividade de hoje, foi pedido que o recálculo do lançamento balístico a cada 0,1 segundo, porém mantendo o tempo real.
Para isto, bastou apenas deixar o Frame Rate no valor de 10(sendo assim a imagem atualizada numa taxa de 10 frames por segundo) e que ao incremento do tempo fosse somado um valor que fosse nesta mesma proporção, como pode ser demonstrado no código abaixo:
void setup(){
frameRate(10);
size(600,600);
}
float tAtual =0;
float aAtual = -10;
int vAtual = 40;
float dEixoX;
float dEixoY;
float soma = float(1)/float(10);
void draw(){
background(255);
mostraGrade();
mostraGradeH();
dEixoX = MRU(float(vAtual), tAtual);
dEixoY = MRUV(vAtual, tAtual, aAtual);
ellipse(dEixoX, 600-dEixoY, 10, 10);
println(tAtual, aAtual, dEixoY, dEixoX);
tAtual = tAtual + soma;
}
float MRUV(float v, float t, float a){
float d;
d = v * t + (a*t*t)/2;
return(d);
}
float MRU(float v, float t){
float d;
d = v * t;
return(d);
}
void mostraGrade(){
for (int i=0; i<12; i++){
line(i*50, 0, i*50, 600);
}
}
void mostraGradeH(){
for(int i=0; i<12; i++){
line(0, i*50, 600, i*50);
}
}
Assinar:
Postagens (Atom)



























