float - azevedolab.net

Transcrição

float - azevedolab.net
azevedolab.net
1
© 2015 Dr. Walter F. de Azevedo Jr.
Definição de Funções em
Processing
Programa flying_saucer01.pde
www.processing.org
O programa flying_saucer01.pde traz um jogo simples que simula a queda de um disco
voador. O disco sofre uma pane em seu motor de dobra espacial, e começa o processo
de queda livre. O único recurso que Zoog e sua intrépida tripulação têm, é tentar ativar
a força de antigravidade auxiliar (antigrav), que pode proporcionar uma queda mais
controlada. No código fazemos uso da variável de sistema mousePressed, para
acionar o antigrav. Vejamos a minha implementação do código. Como temos mais de
40 linhas de código, vamos dividir a explicação em trechos de código. Inicialmente
definimos as variáveis, neste caso, todas do tipo float. As variáveis definidas antes da
definição da função setup() são chamadas variáveis globais, visto que podem ser
chamadas de qualquer parte do programa, ou seja, elas não apresentam abrangência
restrita a uma função, como as variáveis locais que veremos adiante. Em seguida
definimos a função setup(), onde é gerada uma tela de 200 x 480 pixels.
float x = 100;
float y = 0;
float speed = 0;
float gravity = 0.1;
float r;
float g;
float b;
float score;
float score_antigrav
void setup() {
size(200, 480);
}
// x location of flying saucer
// y location of flying saucer
// speed of flying saucer
// gravity acting on the flying saucer
// intensity for red
// intensity for green
// intensity for blue
// score
= 2000; // Initial cutoff value for antigrav
2
Programa flying_saucer01.pde
www.processing.org
Em seguida iniciamos a função draw(), onde atribuímos números aleatórios às
variáveis que serão usadas para definição de cores (r, g, b). Definimos a cor de fundo
como branca, com a função background(255). Depois definimos o desenho do disco
voador, com duas elipses, sendo a menor, que forma a cabine do disco (cockpit) com
cores aleatórias. O corpo do disco voador é de cor cinza, definimos a cor com a função
fill(175). O disco voador é desenhado com as funções ellipse(x, y, 20, 20) (cockpit) e
ellipse(x, y+10, 120,20) (corpo do disco), como detalhado abaixo.
void draw() {
r = random(1,256);
g = random(1,256);
b = random(1,256);
background(255);
// Display the flying saucer
noStroke();
ellipseMode(CENTER);
fill(r,g,b);
ellipse(x, y, 20, 20);
fill(175);
ellipse(x, y+10, 120,20);
3
Programa flying_saucer01.pde
www.processing.org
A variável y, que define a altitude de voo do disco, sofre o incremento do valor atribuído
à variável speed, em seguida a variável speed sofre o incremento do valor atribuído à
variável gravity. Depois, testamos se a altitude de voo (variável y) é maior que o valor
atribuído à variável de sistema height, caso seja o jogo é encerrado. Aproveitamos a
oportunidade para introduzir a função noLoop(), que congela a execução da função
draw(), que pode se reativada, com a função loop(). Na implementação abaixo, após
mostrarmos a mensagem no consolem a execução da função draw() é interrompida.
y = y + speed;
speed = speed + gravity;
// If flying saucer reaches the bottom "Game Over!"
if (y > height) {
println("Your score ", score);
println("Game Over!");
noLoop();
}
4
Programa flying_saucer01.pde
www.processing.org
Em seguida, testamos se a altitude (variável y) é menor que o valor atribuído à variável
de sistema height, caso seja, somamos 1 à variável score, que tem o escore do
jogador. O próximo if testa se o valor atribuído à variável score é maior que aquele
atribuído à variável score_antigrav, inicialmente com valor 2000. Caso seja satisfeita a
condição, mostramos mensagem no console do PDE, subimos o disco subtraindo-se
300 pixels da variável y e somamos 1700 à variável score_antigrav, para que a próxima
ação do antigrav ocorra quando o escore for 3700. Uma observação, este programa foi
testado na versão 2.2 do Processing no Windows, pode ser que em versões anteriores
tenhamos mensagens de erro devido à função println().
// If still flying add one in each cycle
if (y < height){
score = score + 1;
}
// If score > score_antigrav increase height
if (score > score_antigrav ) {
println("Super antigrav!");
y = y -300;
score_antigrav = score_antigrav + 1700;
}
}
5
Programa flying_saucer01.pde
www.processing.org
Lembrem-se que as funções para o desenho de figuras geométricas simples, como a
função ellipse(), usam um sistema de coordenadas baseado na origem à esquerda na
parte superior da tela, ou seja, as coordenadas 0 x 0 pixels, são um ponto à esquerda
na parte mais alta da tela gerada. Ao usamos y = y – 300, estamos subtraindo 300
pixels da variável y, que é usada para a altitude do disco voador, assim, subimos a
representação do disco voador 300 pixels na tela de 200 x 480 pixels. A ideia é darmos
mais tempo de voo para jogador, equivalente a ganharmos uma vida em jogos
tradicionais.
// If still flying add one in each cycle
if (y < height){
score = score + 1;
}
// If score > score_antigrav increase height
if (score > score_antigrav ) {
println("Super antigrav!");
y = y -300;
score_antigrav = score_antigrav + 1700;
}
}
6
Programa flying_saucer01.pde
www.processing.org
Quando o mouse for pressionado, a variável de sistema mousePressed retorna valor
true, e a função mousePressed é executada. Nesta função temos que a velocidade de
queda do disco voador é reduzida, linha vermelha no código abaixo, e mostramos o
valor do escore do jogador no console do PDE. Como já destacado, pode ser que as
funções println() não funcionem no Processing 1.5, principalmente no Mac OS X.
void mousePressed(){
speed = speed * -0.45;
println("Your score",score);
}
7
Programa flying_saucer01.pde
www.processing.org
Abaixo temos uma captura da tela com o disco em ação, quanto mais rápido
pressionamos o mouse, mais ativamos o recurso de antigravidade. Se o jogador
chegar ao escore 2000, o disco sobe 300 pixels, e o jogador tem mais algum tempo de
voo.
8
Programa flying_saucer01.pde
www.processing.org
Exercício: Use o código fonte flying_saucer01.pde para gerar um aplicativo, como
vimos nas aulas anteriores.
9
Funções
www.processing.org
Até o momento usamos funções pré-definidas do Processing, como line(). Iremos ver
como implementar nossas próprias funções, para facilitar a modularização do código,
como vimos na linguagem Python, que podíamos definir nossas próprias funções, com
o uso de def. A estrutura geral da definição de uma função em Processing está
indicada abaixo. O returnedType indica o tipo de variável que é retornada para a
chamada da função. Por exemplo, as funções draw() e setup(), que usamos até agora,
tem como tipo void, ou seja, nada é retornado. Poderíamos ter os tipos usados para
variáveis, como visto na aula passada, por exemplo int. Os tipos das variáveis int,
float, boolean, char etc são chamados de tipo de dados primitivos. O nome da
função é seguido pelos argumentos, que precisam ter suas variáveis definidas. Essas
variáveis são chamadas variáveis locais, e apresentam abrangência restrita à função.
Depois temos a lista de código relacionada à função, que só serão executadas quando
a função for chamada. Por exemplo, podemos chamar a função a partir da função
draw(). Como destacado setup() e draw() são tipos especiais de funções, que são
automaticamente chamadas pelo Processing, as outras funções que definiremos têm
que ser chamadas diretamente, por exemplo, a partir da função draw().
returnedType functionName(arguments){
// Código relacionado à função functionName()
}
10
Funções
www.processing.org
Ilustraremos o uso de funções com um exemplo. Vamos considerar uma função do
Processing para desenhar o nosso disco voador. A definição da função
drawFlyingSaucer segue abaixo. Para desenhar o disco, a função precisa das cores,
para isto introduzimos a função color(), que tem como argumento as variáveis r, g, b,
para definição da cor. Como no argumento da função definimos o tipo da variável,
temos que a variável cockpitColor, é do tipo color. Depois temos as variáveis do tipo
float, para as coordenadas do disco, coordX e coordY. Por último, temos as variáveis
para o tamanho do cockpit do disco, variáveis cockpitX e cockpitY. Um argumento é
simplesmente a declaração de uma variável dentro dos parênteses na definição
de uma função.
void drawFlyingSaucer(color cockpitColor, float coordX, float coordY, float cockpitX, float
cockpitY) {
// Function to display the flying saucer
float saucerX = cockpitX + 100.0;
float saucerY = cockpitY;
noStroke();
ellipseMode(CENTER);
fill(cockpitColor);
// Cockpit
ellipse(coordX, coordY, cockpitX, cockpitY);
fill(175);
// Saucer
ellipse(coordX, coordY+10, saucerX, saucerY);
}
11
Funções
www.processing.org
Agora no código da função, temos a definição das variáveis saucerX e saucerY, que
trazem as coordenadas do corpo da nossa nave. Vejam que estas variáveis são
chamadas de variáveis locais, sua abrangência restringe-se à função
drawFlyingSaucer(), ou seja, não podemos acessar seu valor fora da função. Em
seguida temos as funções noStroke(), que tira o contorno das figuras geométricas, e
ellipseMode(CENTER), que define o modo para as coordenadas do centro da função
ellipse(). Agora definimos a cor de preenchimento, com a função fill(cockpitColor).
void drawFlyingSaucer(color cockpitColor, float coordX, float coordY, float cockpitX, float
cockpitY) {
// Function to display the flying saucer
float saucerX = cockpitX + 100.0;
float saucerY = cockpitY;
noStroke();
ellipseMode(CENTER);
fill(cockpitColor);
// Cockpit
ellipse(coordX, coordY, cockpitX, cockpitY);
fill(175);
// Saucer
ellipse(coordX, coordY+10, saucerX, saucerY);
}
12
Funções
www.processing.org
Em seguida temos duas funções para desenho de elipses, a primeira para o cockpit da
nave e a segunda para o corpo do disco. Antes da chamada da segunda função
ellipse(), chamamos a função fill(175), que define a cor do corpo do disco voador.
Pronto, temos nossa função drawFlyingSaucer(). Agora podemos chama-la a partir da
função draw(). O novo programa que desenha o disco voador chama-se
flying_saucer02.pde
void drawFlyingSaucer(color cockpitColor, float coordX, float coordY, float cockpitX, float
cockpitY) {
// Function to display the flying saucer
float saucerX = cockpitX + 100.0;
float saucerY = cockpitY;
noStroke();
ellipseMode(CENTER);
fill(cockpitColor);
// Cockpit
ellipse(coordX, coordY, cockpitX, cockpitY);
fill(175);
// Saucer
ellipse(coordX, coordY+10, saucerX, saucerY);
}
13
Funções
www.processing.org
O restante do código está abaixo. Não temos novidades na função setup(), só a
definição da tela de fundo. Na função draw() temos a geração de números
pseudoaleatórios, a serem atribuídos às variáveis r, g, b. Depois definimos a cor de
fundo, com a função background(255). E, por último, chamamos a nossa função,
drawFlyingSaucer(). As variáveis e os valores colocados na chamada da função são
chamados parâmetros, como vimos para definição de funções de Python. O processo
onde as informações da chamada da função passam para função, é chamado de
passagem por valor (pass by value).
void setup() {
size(200, 480);
}
void draw() {
r = random(1, 256);
g = random(1, 256);
b = random(1, 256);
background(255);
// Display the flying saucer
drawFlyingSaucer(color(r, g, b), x, y, 20.0, 20.0);
}
14
Funções
www.processing.org
Abaixo temos um diagrama para ilustrar a passagem por valor, da chamada da função,
para a função.
drawFlyingSaucer(color(r, g, b), x, y, 20.0, 20.0);
void drawFlyingSaucer(color cockpitColor, float coordX, float coordY, float cockpitX, float cockpitY)
Pontos importantes:
1) O número de parâmetros deve ser igual ao número de argumentos;
2) Os parâmetros devem está na mesma ordem definida na função;
3) Os parâmetros devem ser do mesmo tipo dos definidos na função;
4) Argumentos agem como variáveis locais à função;
5) Na passagem por valor, é feita uma cópia do valor atribuído à variável, por exemplo,
na variável x (parâmetro), é feita uma cópia do valor atribuído a ela, que então é
passado para variável coordX (argumento). Mudanças do valor atribuído à variável
coordX, não causam mudanças do valor atribuído à variável x.
15
Funções
www.processing.org
Agora podemos usar o que aprendemos sobre funções, para definirmos funções para
cada tarefa do programa flying_saucer01.pde. Chamaremos a nova versão de
flying_saucer03.pde, veja a função draw(), onde fazemos as chamadas das funções. A
primeira função que chamamos é updateY(), que atualiza a coordenada y, a função
seguinte desenha o disco. Depois temos a função gameOver(), que finaliza o jogo,
caso a altitude do disco seja maior que o valor atribuído à variável de sistema height.
Por último temos a função myScore(), que atualiza do escore do jogador em cada ciclo
de execução da função draw(). Fora da função draw() temos a outra função,
previamente vista, mousePressed(). Veremos nos próximos slides a definição das
funções updateY(), gameOver() e myScore().
void draw() {
r = random(1, 256);
g = random(1, 256);
b = random(1, 256);
background(255);
y = updateY();
drawFlyingSaucer(color(r, g, b), x, y, 20, 20);
gameOver(height);
myScore(height);
}
void mousePressed() {
speed = speed * -0.45;
println("Your score", score);
}
//
//
//
//
Calls
Calls
Calls
Calls
updateY
drawFlyingSaucer()
function gameOver()
function updateScore()
16
Funções
www.processing.org
A definição da função updateY() está mostrada abaixo. Veja que a função não tem
argumentos, o valor usado para atualizar a altitude do disco voador é uma variável
global, assim seu valor pode ser acessado e modificado a partir da qualquer função,
inclusive uma que definimos, como a função updateY(). Na definição da função, temos
a atualização da coordenada y, como visto anteriormente, só, que agora, dentro da
função, linhas destacadas em azul. A novidade da função updateY() está no comando
return y, que retorna o valor atribuído à variável y na posição onde a função foi
chamada. Veja que temos que definir o tipo do valor retornado. Notem o float antes do
nome da função. O valor atribuído à variável y é retornado como um float. Assim, como
no Python, faz-se necessário que na chamada da função, esta seja atribuída a uma
variável. Retorne ao slide anterior e veja que o valor retornado pela função updateY() é
atribuído à variável global y.
Tipo do valor retornado
float updateY() {
y = y + speed;
speed = speed + gravity;
return y;
}
Retorna o valor atribuído à variável y
17
Funções
www.processing.org
Vejamos agora a função gameOver(), que tem como argumento a variável heightIn,
definida como do tipo float. Veja que antes do nome da função, temos o tipo void, que
indica que não teremos valores retornados pela função. Nas linhas de comando da
função, temos um condicional if que testa se o valor atribuído à variável global y é
maior que o valor atribuído à variável local heightIn. Os argumentos da função
funcionam como variáveis locais da função, ou seja, heightIn é uma variável local para
função gameOver(), sua abrangência restringe-se à própria função. Na verdade
poderíamos dispensar o uso da variável heightIn, e usar o valor atribuído à variável
sistema height, visto que as variáveis de sistema funcionam como variáveis globais.
Assim a nova função gameOver() não teria argumento.
Tipo do valor retornado
void gameOver(float heightIn) {
if (y > heightIn) {
println("Your score ", score);
println("Game Over!");
noLoop();
}
18
Funções
www.processing.org
A função myScore() tem como argumento a variável do tipo float heightIn. Como visto
para função gameOver(), o valor atribuído a ela é o da altitude do disco. Nos comandos
da função, testamos se o valor atribuído à variável global y é menor que aquele
atribuído à heightIn, caso seja somamos um à variável global score. Depois testamos
se o valor atribuído à variável score é maior que o valor atribuído à variável
score_antigrav, caso seja verdadeira esta condição, subimos a nave 300 pixels e
atualizamos o valor atribuído à variável score_antigrav, somando-se 1700. Veja que
temos o void antes do nome da função, assim não são retornados valores.
Tipo do valor retornado
void myScore(float heightIn) {
if (y < heightIn) {
score = score + 1;
}
// If score > score_antigrav increase height
if (score > score_antigrav ) {
println("Super antigrav!");
y = y -300;
score_antigrav = score_antigrav + 1700;
}
}
19
Métodos
www.processing.org
Tecnicamente, o que chamamos de funções são denominados métodos na linguagem
de programação Java, do qual o Processing é derivado. Assim, na próxima aula
veremos a programação orientada a objeto, onde as funções vinculadas a objetos
serão definidas como métodos.
20
Exercício de Programação: flying_saucer04.pde
www.processing.org
Exercício de programação: Modifique o código do programa flying_saucer03.pde, de
forma que o critério de pontuação fique mais desafiador, por exemplo, modifique o
valor inicial atribuído à variável score_antigrav, tente valores maiores que 2000. Se for
programar no Mac OS X com Processing 1.5, coloque as linhas com as funções
println() como comentários, por exemplo //println(). O restante do código deve funcionar
no Mac OS X com Processing 1.5. Chame o novo programa de flying_saucer04.pde.
Execute o código para ver se o jogo não se tornou muito desafiador.
21
Exercício de Programação: flying_saucer05.pde
www.processing.org
Exercício de programação: Modifique o código do programa flying_saucer04.pde, de
forma que tenhamos um sistema de fases do jogo. Mude a cor de fundo, conforme o
jogador muda de fases. Torne cada fase mais desafiadora que a anterior. Chame o
novo programa de flying_saucer05.pde.
22
Exercício de Programação: flying_saucer06.pde
www.processing.org
Exercício de programação: Modifique o código do programa flying_saucer05.pde, de
forma que tenhamos uma cidade na parte mais baixa do cenário. Adicione prédios e
casas, de forma que a nova altitude para a condição de “Game Over”, leve em conta a
altura dos prédios adicionados ao cenário. Chame o novo programa de
flying_saucer06.pde.
23
Exercício de Programação: flying_saucer07.pde
www.processing.org
Exercício de programação: Modifique o código do programa flying_saucer06.pde,
inclua uma nave mãe, de onde agora o disco voador é lançado. Considere como
critério de vitória, a situação quando o disco voador menor consegue retornar à nave
mãe. Tente diversos esquemas de pontuação, sempre visando que o jogo fique mais
desafiador, conforme o jogador muda de fases. Chame o novo programa de
flying_saucer07.pde. Use o código fonte flying_saucer07.pde para gerar um aplicativo,
como vimos nas aulas anteriores.
24
Referências
www.processing.org
-MODEL, Mitchell L. Bioinformatics Programming Using Python. Sebastopol: O’Reilly Media, Inc., 2011. 1584 p.
-REAS, Casey & FRY, Bem. Geeting Started with Processing. Sebastopol: O’Reilly Media, Inc., 2010. 194 p.
-SHIFFMAN, Daniel. Learning Processing. A Beginner’s Guide to Programming Images, Animation, and Interaction.
Burlington: Morgan Kaufmann, 2008. 453 p.
-SHIFFMAN, Daniel. The Nature of Code: Simulating Natural Systems with Processing. Mountain View: The Nature of Code,
2012. 498 p.
Última atualização: 31 de agosto de 2015.
25

Documentos relacionados

y - azevedolab.net

y - azevedolab.net Em seguida temos a função drawFlyingSaucer(), que desenha o disco voador e tem como argumentos a largura (cockpitX) e a altura (cockpitY) do cockpit.

Leia mais

Arrays - azevedolab.net

Arrays - azevedolab.net Podemos usar o que aprendemos sobre arrays, para criamos um array de objetos. Podemos modificar o programa one_car0.pde, para que tenhamos agora 100 carros. Inicialmente declaramos um array com 100...

Leia mais

speed - azevedolab.net

speed - azevedolab.net O uso de programação orientada a objeto (POO) não irá introduzir necessariamente nenhuma nova função ou comando da linguagem de programação Processing. Usaremos os condicionais, funções e variáveis...

Leia mais