• Nenhum resultado encontrado

Curso rapidíssimo de Processing

N/A
N/A
Protected

Academic year: 2021

Share "Curso rapidíssimo de Processing"

Copied!
11
0
0

Texto

(1)

Curso  rapidíssimo  de  Processing  

Primeira  parte:  bolas  

1. Instale:  http://processing.org/download/.  

2. Crie  uma  pasta  processing,  ao  lado  da  sua  pasta  sources  (a  dos  programas  C).   3. Abra  o  Processing.  

4. Na  janelita  de  edição  que  aparece  vamos  escrever  um  programa,  para  desenhar   um  círculo  vermelho  inscrito  num  quadrado  preto.  

5. Regras  básicas:  

a. A  sintaxe  do  Processing  baseia-­‐se  na  do  Java,  a  qual  se  baseia  na  do  C.   Portanto,  estamos  em  casa!  

b. Nos  programas  mais  simples,  há  apenas  duas  funções:  setup,  que  é   chamada  uma  vez  no  início  do  programa,  e  draw,  que  é  chamada   repetidamente  até  mandarmos  parar  o  programa.  

c. Usaremos  variáveis  “globais”,  declaradas  fora  das  funções,  para  as   grandezas,  cuja  “vida”  de  prolonga  para  além  das  chamadas  das  funções.   6. No  nosso  caso,  para  ilustrar,  queremos  uma  variável  (global)  para  representar  a  

cor  preta  e  outra  para  representar  a  cor  vermelha:    

color black = color(0, 0, 0); color red = color(255, 0, 0);

 

7. O  quadrado  onde  queremos  inscrever  o  círculo  vai  ser  a  janela.  Para  definir  o   tamanho  da  janela,  temos  a  função  size.  Neste  caso,  tudo  o  que  a  função  setup   tem  para  fazer  é  fixar  o  tamanho  da  janela:  

 

void setup() { size(480, 480); }

 

8. Para  desenhar  um  círculo,  usamos  a  função  ellipse  (!!!),  a  qual  tem  quatro   argumentos:  as  coordenadas  do  centro  nos  dois  primeiros,  a  largura  no  terceiro   e  a  altura  no  quarto.  Quando  uma  figura  é  desenhada,  o  seu  interior  sai  com  a   cor  que  tiver  sido  fixada  mais  recentemente  através  da  função  fill.  Antes  de   desenhar,  limpamos  o  fundo,  “pintando-­‐o”  de  uma  cor  pré-­‐determinada,  par   apagar  algum  desenho  que  exista  anteriormente.  Logo,  a  função  draw  fica  assim:     void draw() { background(black); fill(red); ellipse(240, 240, 480, 480); }  

9. O  programa  completo  é  a  concatenação  destas  três  partes:  a  declaração  e   inicialização  das  variáveis  globais,  a  função  setup  e  a  função  draw.  

10. Guarde  o  programa  na  sua  pasta  processing.  Espreite  para  ver  o  que  lá  aparece.   11. Corra  o  programa.  Que  tal?  

(2)

12. Agora  quanto  ao  estilo:  usar  aquelas  constantes  arbitrárias,  480,  240,  espalhadas   no  programa,  não  fica  bem.  O  melhor  é  fixar  as  dimensões  da  janela  por  meio  de   constantes  e  depois  exprimir  os  cálculos  em  termos  dessas  constantes,  ou   equivalente.  Observe,  primeiro  a  declaração  das  constantes:  

 

final int h_side = 480; final int v_side = 480;

 

13. Usamos  estes  valores  como  argumentos  da  função  size:    

void setup() {

size(h_side, v_side); }

 

14. Na  função  ellipse,  o  melhor  é  recorrer  às  variáveis  de  ambiente  width  e  height   que  dão  a  largura  e  a  algura  da  janela  (as  quais  terão  sido  fixadas  através  da   função  size):  

 

void draw() {

background(black); fill(red);

ellipse(width/2, height/2, width, height); }

 

15. Guarde  também  esta  versão.  

16. Se  quisermos  fazer  experiências  com  janelas  de  outros  tamanhos,  porventura   com  janelas  retangulares  com  lados  de  comprimentos  diferentes,  basta  mudar  os   valores  das  constantes.  

17. Agora  experimentemos  uma  variante:  fazer  o  círculo  começar  vazio  e  crescer  até   ao  máximo,  depois  diminuir  até  desaparecer,  depois  aumentar  até  ao  máximo  e   depois  diminuir,  e  assim  sucessivamente.  

18. Precisamos  de  uma  variável,  ou  de  uma  expressão,  para  usar  na  largura  e  na   altura  da  elipse,  em  vez  da  constante  480,  agora  representada  pela  variável   width.  Da  primeira  vez  que  o  círculo  é  desenhado,  a  largura  deve  ser  0;  da   segunda,  1;  depois  2,  3,  ...,  479,  480,  479,  478,  ...,  3,  2  ,1,  0,  1,  2,  etc.  Se  tivermos   uma  variável  inteira  que  conte  o  número  de  vezes  que  a  função  draw  foi  

chamada,  “basta”  transformar  esse  valor  no  correspondente  valor  da  sequência,   assim,  por  exemplo:  

 

int diameter(int x){

int result = x % (width*2); if (result > width)

result = width*2 - result; return result;

}

 

19. Precisamos  de  uma  variável  global  para  contar  as  chamadas  da  função  draw:    

int n_draws = 0;

 

20. Usamos  esta  variável  para  calcular  o  diâmetro,  na  função  draw  e  depois  de   desenhar,  incrementamos:  

(3)

  void draw() { background(black); fill(red); int d = diameter(n_draws); ellipse(width/2, height/2, d, d); n_draws++; }  

21. Guarde  noutro  ficheiro  e  experimente.  

22. A  função  fill  preenche  o  interior  da  figura  que  for  desenhada  a  seguir  com  a  cor   indicada  no  argumento.  O  contorno  da  figura  é  desenhado  com  a  cor  que  tiver   sido  fixada  através  da  função  stroke.  Por  exemplo,  para  desenhar  os  círculos   vermelhos  com  contorno  branco,  faz-­‐se  assim:  

  void draw() { background(black); fill(red); stroke(white); int d = diameter(n_draws); ellipse(width/2, height/2, d, d); n_draws++; }  

23. Mais  interessante  será  desenharmos  vários  círculos,  em  vez  de  apenas  1.  Para   isso  precisamos  de  um  array  de  círculos  e  para  ter  um  array  de  círculos  

precisamos  antes  de  um  tipo  Circle  para  os  círculos.  Na  nossa  aplicação,  um   círculo  é  descrito  pela  sua  cor,  pelas  coordenadas  do  centro  e  pelo  diâmetro.   Observe:     class Circle { color c; int x; int y; int d; }  

24. Para  inicializarmos  os  membros  desta  classe,  usaremos  um  construtor.  Observe:     class Circle { color c; int x; int y; int d;

Circle (color new_c, int new_x, int new_y, int new_d){ c = new_c; x = new_x; y = new_y; d = new_d; } }  

25. Note  que  o  construtor  vem  definido  dentro  da  classe.  

26. Algures  no  programa  haverá  declarações  de  variáveis  globais  assim:    

(4)

Circle c1 = new Circle (red, h_side/2, v_side/2, h_side);

 

27. Ao  longo  da  vida  de  um  círculo,  a  cor  não  muda,  o  centro  também  não,  mas  o   diâmetro  muda.  Por  isso,  a  classe  deve  ter  um  método  para  modificar  o  valor  do   diâmetro:  

 

class Circle { //...

void set_diameter(int new_d){ d = new_d;

} }

 

28. Repare  que  o  método  set_diameter  também  vem  definido  dentro  da  classe,  e  a   atua  sobre  os  membros,  neste  caso  o  membro  d.  

29. Agora,  quando  quisermos  que  o  diâmetro  do  círculo  c1  passe  a  valer  100,  por   exemplo,  programaremos  assim:  

 

c1.set_diameter(100);

 

30. Analogamente,  para  desenhar  o  círculo,  usaremos  um  outro  método  na  classe:     class Circle { //... void draw(){ fill(c); stroke(c); ellipse(x, y, d, d); } }  

31. A  função  draw  para  um  programa  equivalente  ao  nosso  programa  original,  mas   agora  escrito  usando  a  classe  Circle,  fica  assim:  

  void draw() { background(black); int d = diameter(n_draws); c1.set_diameter(d); c1.draw(); n_draws++; }  

32. Não  confunda  as  duas  funções  draw:  uma  é  a  “velha”  função  do  Processing;  a   outra  é  um  método  da  classe  Circle.  

33. O  próximo  exercício  é  desenhar  quatro  círculos,  um  vermelho,  um  verde,  um  azul   e  um  branco,  cada  um  numa  quarta  parte  da  janela,  todos  crescendo  e  

encolhendo  ao  mesmo  tempo.  Como  a  janela  é  quadrada,  com  lado  480,  cada   um  dos  quartos  é  um  quadrado  de  lado  240.  

34. Precisamos  de  quatro  círculos:    

Circle c1; Circle c2; Circle c3; Circle c4;

(5)

   

35. Não  vamos  usar  estes  círculos  um  a  um.  Vamos  sim  metê-­‐los  num  array.   Observe.  Primeiro  as  cores:  

 

color black = color(0, 0, 0);

color white = color(255, 255, 255); color red = color(255, 0, 0);

color green = color(0, 255, 0); color blue = color(0, 0, 255);

 

36. Agora  os  inicializamos  os  círculos,  um  a  um,  logo  na  declaração:    

Circle c1 = new Circle (red, h_side/4, v_side/4, h_side/2); Circle c2 = new Circle (green, h_side/4, 3*v_side/4, h_side/2); Circle c3 = new Circle (blue, 3*h_side/4, v_side/4, h_side/2); Circle c4 = new Circle (white, 3*h_side/4, 3*v_side/4, h_side/2);

 

37. Declaramos  um  array  de  círculos  e  inicializamo-­‐lo  logo:    

Circle[] circles = {c1, c2, c3, c4};

 

38. A  anterior  função  diameter  calcula  o  diâmetro  do  círculo  em  função  do  número   de  vezes  que  o  círculo  já  foi  desenhado,  assumindo  que  o  diâmetro  máximo  é   igual  à  largura  da  janela.  Agora,  cada  círculo  cresce  e  diminui  num  quarto  da   janela,  e  não  na  janela  toda.  Logo,  precisamos  de  uma  função  mais  geral,  em  que   o  diâmetro  máximo  é  parametrizado:  

 

int diameter(int x, int d_max){ int result = x % (d_max*2); if (result > d_max)

result = d_max*2 - result; return result;

}

 

39. Para  desenhar  os  quatro  círculos  do  array,  fazendo-­‐os  crescer  e  encolher,   usamos  um  ciclo  for,  na  função  draw:  

 

void draw() {

background(black); for (Circle c: circles) {

int d = diameter(n_draws, width/2); c.set_diameter(d); c.draw(); } n_draws++; }  

40. Este  ciclo  for  é  muito  castiço,  mas  podíamos  ter  programado  à  moda  antiga:    

void draw() {

background(black);

for (int i = 0; i < 4; i++) {

(6)

int d = diameter(n_draws, width/2); circles[i].set_diameter(d); circles[i].draw(); } n_draws++; }  

41. Quatro  círculos  já  não  é  mau  mas  queremos  mais!  O  exercício  seguinte  continua   a  ser  com  bolas,  mas  agora  queremos  começar  com  zero  bolas  e  fazer  aparecer   uma  nova  bola  a  cada  clique,  com  centro  na  posição  do  clique.  Para  começar,   todas  as  bolas  são  vermelhas  com  diâmetro  máximo  igual  a  metade  da  largura  da   janela.  

42. Como  agora  as  bolas  crescem  e  encolhem  cada  uma  por  si,  o  tamanho  do   diâmetro  não  é  função  do  número  de  vezes  que  a  função  draw  foi  chamada  mas   sim  do  número  de  vezes  que  a  bola  já  foi  desenhada.  Logo,  esse  número  deve  ser   um  membro  da  classe.  Antecipando  o  caso  em  possamos  ter  bolas  com  

tamanhos  máximos  diferentes,  aproveitamos  para  acrescentar  um  membro  para   registar  o  tamanho  máximo:  

  class Circle { color c; int x; int y; int d; int d_max; int n;

Circle (color new_c, int new_x, int new_y, int new_d){ c = new_c; x = new_x; y = new_y; d = new_d; d_max = new_d; n = 0; } void draw(){ fill(c); stroke(c); ellipse(x, y, d, d); n++; }

void set_diameter(int new_d){ d = new_d;

} }

 

43. Na  verdade,  não  é  esta  função  set_diameter  que  nos  faz  falta  neste  problema,   pois  o  que  queremos  é  que  cada  círculo  calcule  o  seu  diâmetro  

automaticamente,  a  partir  de  n  e  d_max.  Usaremos  um  outro  método  para  isso:     class Circle { // ... void set_diameter(){ d = diameter(n, d_max); }

(7)

}

 

44. Já  agora,  repare  que  temos  dois  métodos  com  o  mesmo  nome  (o  que  faz  algum   sentido,  pois  fazem  mais  ou  menos  a  mesma  coisa)  e  que  se  distinguem  pela  lista   de  argumentos.  

45. Agora  o  número  de  círculo  não  é  fixo.  O  array  começa  vazio  e  de  cada  vez  que  há   um  clique,  um  novo  círculo  é  acrescentado  ao  array.  Eis  a  declaração:  

 

final int max_circles = 64;

Circle[] circles = new Circle[max_circles]; int n_circles = 0;

 

46. A  função  mousePressed  é  chamada  de  cada  vez  que  há  um  clique:  o  que  lá   programarmos  será  executado  em  resposta  a  cada  clique.  Neste  caso,  o  que   queremos  fazer  é  criar  acrescentar  um  novo  círculo  ao  array:  

 

void mousePressed(){

if (n_circles < max_circles)

circles[n_circles++] = new Circle(red, mouseX, mouseY, width/2); }

 

47. Antes  de  desenhar  cada  círculo,  atualizamos  o  seu  diâmetro:    

void draw() {

background(black);

for (int i = 0; i < n_circles; i++) { circles[i].set_diameter(); circles[i].draw(); } }  

48. Note  que  aqui  não  podemos  usar  aquele  ciclo  for  castiço  pois  nem  todos  os   elementos  do  array  estão  preenchidos.  

49. Nos  exercícios  que  temos  estado  a  estudar,  os  círculos  não  mudam  de  sítio,   mudam  apenas  de  tamanho.  Vejamos  agora  um  caso  em  que  os  círculos  se   mudam  de  sítio,  isto  é,  em  que  o  centro  se  desloca.  Queremos  um  programa  que   crie  um  círculo  no  local  do  clique  e  que  depois  esse  círculo  “caia”,  deslocando-­‐se   verticalmente  até  sair  da  janela.  Para  ser  mais  variado,  o  diâmetro  do  círculo  será   um  número  aleatório  entre  10  e  100  (inclusive)  e  o  a  velocidade  vertical  será  um   número  aleatório  entre  1  e  4  (inclusive).  Note  bem:  se  a  velocidade  vertical  for   dy,  então  da  próxima  vez  o  círculo  deve  ser  desenhado  dx  pontos  mais  abaixo.   Precisamos  de  constantes  para  estas  quatro  grandezas:  

 

final int dy_min = 1; // minimum vertical speed final int dy_max = 4; // maximum vertical speed final int d_min = 10; // mininum diameter

final int d_max = 100; // maximum diameter

 

50. Neste  exemplo,  cada  círculo  é  caracterizado  pela  cor,  pelas  coordenada  do   centro,  pelo  diâmetro  e  pela  velocidade  vertical.  

 

(8)

color c; int x; int y; int d; int dy;

Circle(color new_c, int new_x, int new_y, int new_d, int new_dy) { c = new_c; x = new_x; y = new_y; d = new_d; dy = new_dy; } void draw() { fill(c); stroke(c); ellipse(x, y, d, d); } }  

51. Precisamos  agora  de  um  método  para  mover  um  círculo:     class Circle { // ... void move() { y += dy; } }  

52. A  função  mousePressed  é  análoga  à  anterior:    

void mousePressed() {

if (n_circles < max_circles) {

int dx = (int) random(dy_min, dy_max+1); int d = (int) random(d_min, d_max+1);

circles[n_circles++] = new Circle(red, mouseX, mouseY, d, dx); }

 

53. Repare  na  forma  de  usar  a  função  random.  

54. Neste  exemplo,  introduzimos  a  função  update  para  concentrar  todos  os  cálculos   que  determinam  a  forma  no  novo  desenho,  antes  de  cada  chamada  da  funçãoo   draw:  

 

void update() {

for (int i = 0; i < n_circles; i++) {

circles[i].move(); }

}

 

55. Eis  a  função  draw:    

void draw() {

background(black); update();

for (int i = 0; i < n_circles; i++) {

(9)

circles[i].draw(); }

}

 

56. O  programa  produz  o  efeito  visual  pretendido,  mas  podemos  notar  que  as  bolas   que  já  saíram  da  janela  continuam  a  ser  desenhadas  ainda  que  não  se  vejam.  Isto   é,  o  computador  gasta  energia  com  cálculos  desnecessários.  Seria  melhor  retirar   do  array  os  círculos  que  já  saíram  da  janela.  O  próximo  exercício  é  para  ilustrar   esta  situação.  

57. Queremos  agora  um  programa  que  crie  bolas  à  velocidade  de  tantas  por   segundo,  bolas  essas  que  entram  por  cima  e  vão  caindo  até  baixo.  A  cor,  a   coordenada  x  do  centro,  o  diâmetro  e  a  velocidade  de  queda  são  escolhidas   aleatoriamente,  entre  limites  dados.  

58. Eis  uma  função  para  geral  uma  cor  aleatória:    

color random_color(){

int r = (int) random(0, 256); int g = (int) random(0, 256); int b = (int) random(0, 256); return color(r, g, b);

}

 

59. Neste  exercício  os  círculos  são  como  os  do  exercício  anterior,  com  cor,  

coordenadas  do  centro,  diâmetro  e  velocidade  de  queda.  Precisamos  apenas  de   mais  um  método  para  decidir  se  um  círculo  é  visível  (ainda  que  parcialmente):    

class Circle { // ...

boolean visible(){

return y + d/2 >= 0 && y - d/2 <= height; }

}

 

60. Para  criar  um  círculo  aleatório,  colocado  sobre  o  lado  de  cima  da  janela,   podemos  usar  a  seguinte  função:  

 

Circle random_circle(){

int x = (int) random(0, width+1);

int dy = (int) random(dy_min, dy_max+1); int d = (int) random(d_min, d_max); color c = random_color();

return new Circle(c, x, -d/2, d, dy); }

 

61. Periodicamente,  precisamos  de  retirar  do  array  os  círculos  que  deixarem  de  ser   visíveis:  

 

int prune_invisibles(Circle[] c, int n){ int result = 0;

for (int i = 0; i < n; i++) if (c[i].visible())

c[result++] = c[i]; return result;

}

(10)

62. Outra  operação  sobre  o  array  dos  círculos,  a  realizar  antes  de  desenhar,  é  mover   cada  um  deles:  

 

void move_all(Circle[] c, int n){ for (int i = 0; i < n; i++) c[i].move();

}  

 

63. A  frequência  de  criação  de  círculos  estará  fixada  numa  constante:    

final float frequency = 4; // max number of balls created per second

 

64. Assim,  só  devemos  criar  novos  círculos  quando  o  número  de  círculos  já  criados   for  menor  do  que  o  tempo  decorrido  vezes  a  frequência.  Logo,  precisamos   também  de  uma  variável  para  o  número  de  círculos  criados:  

 

int n_balls = 0;

 

65. A  função  update,  chamada  antes  de  fazer  o  desenho,  move  os  círculos,  remove   os  que  ficam  invisíveis  e  cria  um  novo  círculo  se  for  altura  de  o  fazer:  

 

void update(){

move_all(circles, n_circles);

n_circles = prune_invisibles(circles, n_circles); if (n_balls < millis() / 1000 * frequency && n_circles < max_circles){ circles[n_circles++] = random_circle(); n_balls++; } }  

66. A  função  draw  é  como  de  costume  e  a  função  setup  também.  

Segunda  parte:  mais  funções  

67. Até  agora,  só  desenhamos  bolas,  usando  a  função  ellipse.  Para  desenhar  outras   figuras  básicas,  temos  as  seguintes  funções:  

a. arc()   b. line()   c. point()   d. quad()   e. rect()   f. triangle()  

g. beginShape(),  endShape(),  vertex()  

Terceira  parte:  exercícios  com  bandeiras  

68. Escreva  programas  para  desenhar  as  bandeiras  da  França,  da  Suíça,  da  Suécia,  da   Noruega,  da  África  do  Sul,  do  Reino  Unido,  da  República  Checa  e  outras  formadas   só  por  zonas  triangulares  ou  quadrangulares.  Ou  então  invente  uma  nova  

(11)

bandeira  nacional,  só  usando  o  verde  e  vermelho,  mas  numa  disposição  original.   Escolha  aquela  de  que  gostar  mais,  e  submeta  na  tarefa  A.  

69. Escreva  um  programa  para  desenhar  uma  estrela  de  cinco  pontas  no  meio  de   uma  janela  retangular.  Use  uma  classe  Star,  análoga  a  Circle,  para  este  efeito.   Submeta  na  tarefa  B  

70. Acrescente  à  classe  Star  uma  operação  para  rodar  uma  estrela  de  um  ângulo   dado.  Use-­‐a  para  animar  uma  estrela,  fazendo-­‐a  rodar.  Submeta  na  tarefa  C.   71. Repita  o  exercício  anterior  para  várias  estrelas,  rodando  umas  para  a  esquerda  

outras  para  a  direita.  Submeta  na  tarefa  D.  

72. Escreva  programas  para  desenhar  as  bandeiras  dos  Estados  Unidos,  da  China,  da   de  Somália,  de  Cuba,  e  outras  que  usam  estrelas.  Escolha  uma  delas  e  submeta   na  tarefa  E.  

73. Escreva  um  programa  para  desenhar  o  logótipo  da  Universidade  do  Algarve.   Submeta  na  tarefa  F.  

74. Idem,  com  uma  animação  original.  Submeta  na  tarefa  G.  

75. E,  para  terminar,  um  clássico:  escreva  um  programa  para  desenhar  um  relógio   analógico,  com  um  design  original  seu!  Submeta  na  tarefa  H.  

76. Update:  como  há  um  exemplo  na  documentação  que  é  precisamente  um  relógio   analógico,  acrescentamos  mais  uma  tarefa,  para  fechar  a  nossa  cadeira  em   beleza:  uma  animação  do  bubblesort  ou  de  um  outro  algoritmo  de  ordenação  à   escolha.  Submeta  na  tarefa  I.  

Referências

Documentos relacionados

A evolução da integração do texto escrito – expressão do narrador, diálogos dos personagens e onomatopéias – na História em Quadrinhos, como a tentativa dessa forma de

(...) Portanto, para que os instrumentos possam ser construídos, o homem necessita &#34;pesquisar, planejar e criar tecnologias”.. Hoje a era digital apresenta um

A hipótese H6 não se confirma, dado que não se encontraram diferenças significativas entre os dois grupos de inquiridos: os que vivem até 5km e os que vivem a mais de 6km, ou

Diante disso nos surgem duas explicações principais, sendo a primeira a hipótese de ter havido a marcação de algum antígeno nuclear que não o transportador GLUT-1 pela

Outra classificação dos miomas submucosos é a classificação STEPW, que não só classifica o mioma em relação ao útero, mas também identifica o grau de dificuldade da cirurgia e

This study showed that the Brazilian European Health Literacy survey, HLS-EU-BR, could differentiate the health literacy levels of a diversified sample of higher education (university

As participantes não tiveram benefícios diretos, no entanto, suas entrevistas contribuíram para o melhor conhecimento do significado da dor do parto, o que pode