Skip navigation

instalar, instalar, abrir os programas, correr exemplos teste, primeiras noções de programação.

a primeira aula foi em torno de uma abordagem aos programas que vamos usar ao longo do curso, bem como da análise da bibliografia que nos vai acompanhar, e finalmente uma primeira abordagem às linguagens de programação e principalmente, programação por objectos.

ainda falta instalar os compiladores nas máquinas para ter o openframeworks a funcionar (para os mac’s, instalar o x-code, para os pc’s, instalar o code::blocks), mas já conseguimos abrir o processing, pd e arduino, o que não foi nada mal para primeira sessão.

o tema principal desta primeira sessão foi a análise de um primeiro programa exemplo em processing, que já usa programação por objectos. vimos que cada variável tem um tipo, e que esse tipo pode ser ou um tipo básico de dados (boolean, int, float, char, string…), ou então um tipo/class/objecto por nós preparado, que consiste no diferente re-arranjo de várias variáveis de tipos básicos.

assim, quando na primeira linha do programa declaramos uma variável que se chama circulo do tipo Circulo, estamos já a pressupor que este tipo Circulo está por nós definido algures.

Circulo circulo;

na definição dos objectos vimos que os pontos principais correspondem à criação de variáveis membro que fazem parte desse mesmo objecto, bem como das funções próprias de cada classe. A função principal que é chamada aquando da criação do objecto é o chamado construtor, que instancia variáveis e lhes atribui valores.

o objecto Circulo está definido como:

class Circulo {

float posx, posy, rad;

Circulo(){
rad = random(10,30);
posx = random(rad,width-rad);
posy = random(rad,height-rad);
}

void draw(){

stroke(0);
fill(82,247,195);

ellipse(posx,posy,rad,rad);

}

void reset(){
posx = random(rad,width-rad);
posy = random(rad,height-rad);

}

}

o objecto Circulo tem 3 variáveis fraccionárias, posx, posy, e rad. o construtor do objecto quando é chamado atribui valores aleatórios a cada um destes campos e que têm a ver com a própria variável. o raio, rad, só tem valores de 10 a 30, as posições têm valores entre rad e largura e altura menos rad, para que sejam instanciados dentro da tela. além do construtor do objecto, temos mais duas funções, uma chamada draw e outra chamada reset, ambas do tipo void, porque não devolvem parâmetros nenhuns (por oposição à função random que devolve um parâmetro float quando é chamada)

o objecto circulo do tipo Circulo é criado na função setup(), através desta linha:

circulo = new Circulo(); // criar um novo circulo

depois desta linha ser executada, temos a certeza que a nossa variável circulo tem agora três campos, já com valores atribuídos, valores esses que são aleatórios, ie, calculados através do random(min,max). podemos aceder aos campos para os usar em funções fora da classe através do ‘.’, ex:

circulo.posx = 100; // colocar a variável posx do obj circulo com o valor 100
circulo.rad = (2*frameCount % 50); // atribuir ao raio duas vezes o número de frames que já passaram, entre 0 e 50

circulo.posy = circulo.posy + 1; // novo valor de y é igual ao valor antigo mais 1

ou então, dentro do próprio objecto, não precisamos do ponto para aceder aos valores da função. reparem que na função draw acedemos aos valores actuais posx, posy, e rad sem usarmos o ponto, pois estamos dentro do objecto.

além de aceder às variáveis fora do objecto, podemos aceder às funções:

circulo.draw(); // chamar a função draw do objecto circulo

circulo.reset(); // chamar a função reset do objecto circulo

e pronto, feito o objecto, podemos agora começar a brincar com ele/eles.(eles + à frente).

lembrem-se que no processing a função setup é corrida em primeiro lugar uma única vez, que serve para inicializar janela/som/variáveis/etc. depois é a função draw que faz um loop contínuo infinito até que optemos por terminar o programa com o esc.

esta função draw executa os seguintes passos:

1. background (58,95,83);
2. go_mouse();
3. circulo.draw();

1. apaga sempre a frame anterior e preenche a tela com aquela cor rgb
2. mexe nas coordenadas do círculo em função do pressionamento do botão
3. desenha o círculo com as coordenadas actuais

e faz estes 3 passos continuamente, em loop.

a função go_mouse é que mexe nas coordenadas do círculo, em função das coordenadas do rato e se carregamos no botão.

é definido principalmente com um bloco de código

if (condição v ou f) {
//este código é executado se a condição for V
} else {
//este código é executado se a condição for F
}

e a nossa condição é o mousePressed. se o rato for premido, o círculo tende a ir ter com a posição do rato, se for largado, o circulo afasta-se do rato. usamos um low pass filter para alterar as posições, é um filtro comum e simples que suaviza as transições de valores.

assim, o programa completo para adicionar à classe Circulo criada acima é o seguinte:

/// circulo , processing, som do pensamento

Circulo circulo; //declarar a variável do tipo Circulo

void setup(){
size(500,281); // criar uma janela
circulo = new Circulo(); // criar um novo circulo

//overwrite dos valores das variáveis mouse e mousePressed
mouseX = width/2;
mouseY = height/2;
mousePressed = true;
}

void draw(){

background (58,95,83);
go_mouse();
circulo.draw();

}

void go_mouse(){

if(mousePressed){
// um filtro low pass ao movimento com destino ao rato
float filter = 0.01;
circulo.posx = circulo.posx * (1.0-filter) + mouseX * filter;
circulo.posy = circulo.posy * (1.0-filter) + mouseY * filter;
} else {
//se o rato não premido, afastamo-nos
float filter = 0.01;
// calcular um vector com origem no rato até ao circulo
float dx = circulo.posx – mouseX;
float dy = circulo.posy – mouseY;
// as coordenadas de destino são a posição do círculo + o vector
circulo.posx = circulo.posx * (1.0-filter) + (circulo.posx +dx) * filter;
circulo.posy = circulo.posy * (1.0-filter) + (circulo.posy +dy) * filter;

}

}

outro ponto importante que observámos foi a localidade das variáveis. posso ter duas variáveis filter dentro desta função go_mouse() porque o seu alcance não se toca, estão em níveis distintos, podem ter valores diferentes, só existem dentro das chavetas em que são declaradas.

este programa instancia apenas um círculo, de seguida, vimos um programa que instancia N circulos, e a grande alteração foi inserir os ciclos for e alterar a variável circulo para uma array de variáveis circulos.

este é o segundo programa, mantendo a classe Circulo acima definida.

Circulo circulos[];
int NUM_CIRCULOS = 10;

void setup(){
size(500,281); // criar uma janela

circulos = new Circulo[NUM_CIRCULOS]; // criar espaço na memória para N variáveis do tipo Circulo
for(int i=0; i<NUM_CIRCULOS; i++) {
circulos[i] = new Circulo(); // instanciar cada uma das variáveis Circulo
}

//overwrite dos valores das variáveis mouse e mousePressed
mouseX = width/2;
mouseY = width/2;
mousePressed = true;
}

void draw(){

background (58,95,83);
go_mouse();
for(int i=0; i<NUM_CIRCULOS; i++) {
circulos[i].draw();
}

}

void go_mouse(){

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

if(mousePressed){
// um filtro low pass ao movimento com destino ao rato
float filter = 0.01;
circulos[i].posx = circulos[i].posx * (1.0-filter) + mouseX * filter;
circulos[i].posy = circulos[i].posy * (1.0-filter) + mouseY * filter;
}
else {
//se o rato não premido, afastamo-nos
float filter = 0.01;
// calcular um vector com origem no rato até ao circulo
float dx = circulos[i].posx – mouseX;
float dy = circulos[i].posy – mouseY;
// as coordenadas de destino são a posição do círculo + o vector
circulos[i].posx = circulos[i].posx * (1.0-filter) + ( circulos[i].posx +dx) * filter;
circulos[i].posy = circulos[i].posy * (1.0-filter) + ( circulos[i].posy +dy) * filter;
}

}

}

as alterações não são muitas, e já podemos ver a riqueza de começar a programar com objectos: agora com o mesmo código que tinhamos usado para apenas um circulo, podemos ter o mesmo comportamento para N circulos.

algumas imagens dos programas com 1 circulo e N circulos

circulo_26

circulos31

no fim da aula o nuno disse-me que com mil circulos a coisa já ficava lenta. pois é. o comando para desenhar um círculo (ellipse no processing) é mais pesado que o comando para desenhar um quadrado. a outra coisa que lhe mostrei foi o mesmo código em c++ no openframeworks, e aí os mil círculos já andavam bem a 60 frames por segundo.

ainda antes de terminar a primeira aula, vimos a funcionar um programa mais avançado, que consistia em duas partes a comunicar por rede através do protocolo OSC (open sound control) no próprio computador. uma parte para analisar blobs no movimento da imagem, a outra parte sintetisa som a partir das coordenadas das blobs. a parte que analisa a imagem pelas blobs, construí há pouco tempo uma aplicação no openframeworks para ter a melhor performance possível na parte da análise de imagem. chama-se blosc e têm o código na pasta da aula, bem como binários para o osx prontos a executar aqui. a segunda parte é um patch em pure data, que recebe na própria máquina, na port 7737, os valores calculados pela aplicação e usa os valores para controlar 10 osciladores que funcionam de acordo com as blobs analisadas.

aqui ficam imagens em funcionamento dos dois programas, e serve já para uma introdução a síntese sonora, sendo que o som e a continuação da análise de tarefas simples de programação é o que nos vai ocupar nos próximos tempos.

blosc-34

blosc-pd-37

até para a semana! leiam se puderem os livros, começem a ler os capítulos introdutórios que têem estas noções sobre variáveis e objectos e ciclos, etc, e tragam dúvidas que encontrem pelo caminho. boas leituras.

Anúncios

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s

%d bloggers like this: