sexta-feira, 30 de março de 2018

MAMI - Aula #9


Essa tarefa é a 2ª mais simples até agora, ela é basicamente sobre proporção.

Primeiro vou criar 2 variáveis para pegar as posições x e y relativas do mouse, a ideia é encontrar a fração do tamanho da tela onde o mouse está:

  mouseXrelative = 1.0*mouseX/width;
  mouseYrelative = 1.0*mouseY/height;

A multiplicação do primeiro valor por 1.0 é para transformar ele em floar, senão o programa vai retornar sempre o valor 0.

Depois eu poderia apenas por os valores que a tarefa pediu, mas acho que é interessante mostrar uma ideia que usei em uma das telas do jogo feito no primeiro semestre do curso:

if((propY)*width<(propX)*height){
   widthRes = width;
   heightRes = (propY/propX)*widthRes;
}
else{
   heightRes = height;
   widthRelative = (propX/propY)*heightRes;
  
}

A propX e a propY são variáveis onde eu ponho o tamanho do objeto, nesse caso eu usei a proporção de 14:9 que a tarefa pediu, o widthRes e o heightRes aqui vão ser a largura e a altura resultantes.

Pra explicar a ideia eu vou precisar desenhar(até porque foi a forma como eu pensei):

Suponhamos que temos um retângulo dentro de outro e queremos aumentar o tamanho dele proporcionalmente, de forma que nem a altura e nem a largura ultrapassem a do retângulo maior.


Nós aumentamos proporcionalmente até pararmos no limite da largura ou da altura. Até que um dos lados do retângulo menor se torne igual a um dos lados do maior.


A equivalência " 16/9 = largura/altura " ou "16*altura = 9*largura" é válida para o retângulo menor que estamos tentando achar, mas repare que para o retângulo maior, a diferença entre a largura ou a altura dele dentro dessa proporção vão transformar o "=" em "<" ou ">", é daí que surge o "if((propY)*width < (propX)*height)".

Explicando de forma mais simples, se o lado da largura é o menor, isso significa que, na hora de aumentar o retângulo menor, a largura dele chega na largura do maior antes da altura dele chegar na altura do maior, nesse caso nós usamos a largura do maior como base, caso contrário, usamos a altura do maior.


Voltando à tarefa, já que tenho uma representação da tela na proporção escolhida, vou aproveitar ela e fazer o retângulo pedido na tarefa a partir de 1 quarto dela, já aproveitar para pegar a posição x e y dele, que vão ser usadas jajá:

rect(x=(width/2-largura/2),y= (height/2-altura/2), largura, altura);

O outro pedido da tarefa é desenhar uma bolinha dentro deste retângulo de forma que a posição dela seja proporcional à posição do mouse na tela, pra isso vamos usar as posições relativas criadas lá no início do post:

ellipse(x+(mouseXrelative*largura), y+(mouseYrelative*altura), 10, 10);

E pronto, a tarefa está feita!






sábado, 24 de março de 2018

Mami - Aula #7

Nessa aula nós vimos como desenhar a bandeira do Japão e como fazer ela seguir o mouse:


A bandeira do Japão foi bem simples, mas a tarefa agora é desenhar a bandeira do Brasil segundo a legislação.



Felizmente dessa vez está liberado o uso do rectMode, o que vai permitir que eu mude o padrão de desenho do programa do retângulo do canto superior esquerdo para o centro, e isso vai facilitar na hora de fazer os cálculos do posicionamento, já que não vai ser preciso calcular a diferença de onde o círculo e o retângulo são desenhados.

Eu vou fazer apenas modificações na função da bandeira do Japão mudando ela para uma função que desenha a bandeira do Brasil, para começar, em vez da largura, os tamanhos vão ser calculados pela altura, e o módulo vai ser 1/14 da altura.



Não tem tanto o que explicar, o retângulo ficou mais fácil de desenhar com o rectMode, o losango só precisou por as coordenadas dos pontos em ordem horária, e o círculo só mudou o valor do diâmetro. Eu adicionei também um evento de mouseWhell para alterar o valor que dá a altura da bandeira, mas fiz isso só pra testar se estava tudo ok.



Download do arquivo do processing aqui!

Mami - Aula #6

Após algumas leves modificações, o nosso código da aula passada chegou até este ponto. Estou usando o tipo float para as variáveis porque é melhor de trabalhar e arredondando o valor do MRU e do MRUV(que foi adicionado) pro movimento ficar mais condizente com o modelo matemático.



A tarefa dessa vez será desenvolver uma aplicação que simule o quicar de uma bola, perdendo velocidade com o passar do tempo.

A principal mudança no código vai ser o uso de novas variáveis para guardar alguns valores sobre a bolinha no momento que ela quicar, a ideia é resetar o tempo toda vez que a bola quicar e diminuir a velocidade, dessa forma o próximo movimento dela vai ter as mesmas características do primeiro.

A bola começa do chão, é lançada para cima com uma certa velocidade(que é definida no setup), desacelera e cai por conta da gravidade, e quando bate no chão, é lançada novamente para cima mas a partir do ponto no eixo X de onde ela caiu.


Não tem tanto segredo, teve só um problema com as quicadas infinitas por conta da aceleração, a solução foi deixar a grav em 0 quando a velocidade estivesse abaixo de 1, que de certa forma é uma forma de simular a força normal.



Download do arquivo do processing aqui!

quinta-feira, 22 de março de 2018

Mami - Aula #5

Na 5ª aula de Mami nós vimos como fazer um programa que simula o deslocamento retilíneo de um corpo durante uma variação de tempo:



Nós usamos uma estratégia bem simples para simular a passagem de tempo: a frameRate ficaria em 1 e uma variável ganharia +1 a cada atualização da Draw. Dessa vez a tarefa é apenas criar uma solução onde a variação de tempo seja simulada com uma frameRate maior para que o programa rode suavemente.

Para evitar a fadiga, eu vou resolver isso fazendo apenas uma leve alteração em 1 linha:


O processing tem uma variável dele mesmo que guarda a quantidade de frames que o programa já rodou, a frameCount, e tem uma variável que guarda a quantidade de frames por segundo, a frameRate, se eu dividir a quantidade de frames total pela quantidade de frames por segundo, eu tenho a quantidade de segundos passados.

O programa ainda vai desenhar a elipse em todos os frames, mas a posição dela vai atualizar junto com o tempo(por conta da fórmula do MRU), e como a variável do tempo é inteira, ela vai ignorar as frações e desenhar sempre na distância referente ao valor inteiro do tempo.



Download do arquivo do processing aqui!

Mami - Aula #4

Bons ventos para os navegadores incansáveis da internet!

Dessa vez a  tarefa é mais complexa:

Para realizar tal ato, a primeira coisa que irei fazer é baixar uma biblioteca que já vai ter as sliders codificadas, essa biblioteca pode ser baixada do site http://www.sojamo.de/libraries/controlP5/ ; basta descompactar dentro da pasta "libraries" do processing.

O bloco eu também irei partir do arquivo feito em sala de aula:


Bem, para começar, eu adicionei as sliders e fiz algumas alterações no código, primeiramente eu apenas tentei achar uma posição legal, e achei interessante elas ficarem na parte de cima da tela, mostrando pro usuário que ele pode fazer a alteração nos blocos logo de início.



Depois eu comecei a desenvolver e testar uma fórmula para criar os blocos dentro de um laço duplo, o resultado foi este:


Que basicamente significa que cada bloco vai ser desenhado a partir do centro, com um desconto equivalente à quantidade total(quantx e quanty) de blocos e um acréscimo equivalente ao número atual(i e j) de blocos. Os números 50 e 100 são por conta do tamanho do bloco, mas vou substituir por uma variável e transformar isso em uma função nova pra facilitar o trabalho.



Agora nós temos as sliders e a função que desenha o quadro, falta apenas o comando para desenhar ele quando o valor das sliders for alterado.

Eu tentei usar o código do exemplo deste site para fazer isso, mas deu algo errado e eu não conseguir fazer da mesma forma. Então eu fui neste site atrás das funções na tentativa de achar algum "getValue", pois esse "get" é geralmente usado pra nomear funções que guardam algum valor, e por sorte eu achei exatamente o que estava procurando, o nome da função era o mesmo que eu imaginava...

Criei 2 variáveis globais(pra não ter erro) para receber o valor inteiro de cada slider, e usei essas variáveis para desenhar a pintura. Eu não queria por ela no draw pois eu queria que a pintura atualizasse apenas após eu mexer nas sliders, e como não deu pra fazer igual no exemplo, eu pensei em outra solução: Tem uma coisa que acontece sempre que eu mexo nas sliders, que é um mouseReleased, então eu posso usar um evento disso para fazer a pintura:





Download do arquivo do processing aqui!

domingo, 11 de março de 2018

Mami - Aula #3

Olá mais uma vez!

Dessa vez a tarefa é fazer um programa que centralize na tela dele n quadrados de 50 x 50 pixels.

Porém tem um detalhe: eu terei que usar as ferramentas de debug e tweak do processing durante o processo e explicar como usá-las para facilitar o trabalho.

O Debug eu uso para testar o resultado das fórmulas e ver se as variáveis estão mesmo recebendo os valores que tem que receber, eu fiz esse teste e está tudo ok.





Porém o programa não está funcionando como deveria, o que poderia ser?





A ferramenta tweak possibilita que eu altere variáveis dentro do void draw enquanto o programa está rodando, então eu vou levar as minhas variáveis do setup pro draw para poder mexer nelas e ver o que acontece:

 



Ok, depois desses testes eu percebi que a fórmula que define a posição x dos quadrados está uma merda, então eu farei mais alguns testes nela usando o debug, e pra isso, eu vou usar uma nova variável que vou chamar de test para receber o valor da tal fórmula para que ele possa aparecer no debug e eu possa saber o valor dela:




Dessa vez eu descobri que a posição x está começando do 92 e pulando de 100 em 100.

Bem, pra começar ela deveria estar começando do 42, então eu tenho o valor de l além do valor correto, e isso acontece por conta do +l*(i+1). O primeiro quadrado deveria considerar o i=0 e isso deveria anular as somas referentes aos novos quadrados, a minha fórmula está fracassando em matar essas adições no i=0, além de estar fazendo a soma de forma errada já que deveria estar somando +92 e não +100.

Pra resolver isso eu vou estruturar a fórmula para space + i*(l+space), dessa forma, eu vou começar do valor do space no i=0 e nos demais valores de i ou vou adicionar o respectivo múltiplo de (l+space), que é o valor do lado do quadrado mais o espaço entre quadrados;

Vamos testar isso de novo com o tweak:



Agora deu certo, o programa rodou e eu finalmente poderei dormir(vou ter pesadelo com isso, certeza).

Até a próxima!


Download do arquivo do processing aqui!

Mami - Aula #2 - Projeto

Nessa aula foi apresentado o projeto mas não foi passada nenhuma tarefa.

O projeto é refazer um jogo da segunda geração, o jogo que escolhi foi o Star Castle do Vectrex. Eis abaixo um vídeo do jogo:




O Vectrex foi fabricado entre 1982 e 1984 e foi primeiro console a usar a tecnologia de vetores que era usada nos monitores de jogos arcade, foi um sucesso no seu lançamento mas a crise dos video-games de 83 acabou pegando em cheio quando tentaram dar continuidade no projeto, e acabou que ele foi descontinuado em 84.

O Star Castle é um jogo que foi lançado pela Cinematronics em 1980 que consiste em destruir uma nave inimiga que fica protegida por octógonos(como muralhas de castelo). Em 1983 ele foi portado para o Vectrex mas não teve um grande destaque, porém foi/é um jogo bem interessante.

O meu objetivo é fazer um jogo no Processing inspirado no Star Castle do Vectrex, e inclusive sem o uso de arquivos de imagens.








Primeira mecânica: desenho das naves.

 
Modelo natural


Para começar, eu quero desenhar a nave através de linhas. No Processing uma linha é desenhada a partir de 2 pontos, abaixo seguem os desenhos que eu quero realizar(vou precisar de muitos pontos...):






A princípio seria bastante fácil apenas ligar os pontos baseado nas posições deles nesse desenho, mas é preciso ter em mente que ambas as naves giram, e é preciso levar o ângulo da nave em conta na hora de desenha-la.

Já que é preciso levar sempre em conta o ângulo, a minha ideia foi desenhar a nave a partir de um círculo e usar as relações de seno e cosseno para identificar as posições dos pontos dentro do círculo



Para calcular a posição de cada ponto é só ter a distância do ponto até o centro do círculo o ângulo em que esse ponto está, abaixo eu tentei representar isso:


Modelo Matemático

Eu pude ver os ângulos e as hipotenusas desenhando no Corel um círculo de 100x100, no Processing eu pus a distância do centro ao ponto relativa ao tamanho do raio do círculo, o tamanho de 100x100 me ajudou nesse processo. Aqui a posição o ponto no eixo x pode ser calculada a partir do cosseno e no eixo y a partir do seno, e o Processing já tem funções que fazem esse cálculo apenas passando o ângulo, depois foi só multiplicar pela hipotenusa e foi sucesso.

O modelo computacional segue neste link







Segunda mecânica:


Com a minha nave principal desenhada, eu quero fazer com que ela se mova pela tela.


Modelo Natural


Para entender como funciona o deslocamento, dividi ele em 4 aspectos:

Posição
Velocidade
Aceleração
Ângulo

A aceleração é a variação de velocidade, isso significa que ela vai determinar as mudanças na velocidade da nave.

A velocidade é a variação de posição, isso significa que ela vai determinar as mudanças de posição da nave.

A posição é basicamente o ponto onde a nave vai ser desenhada.

O ângulo vai determinar como a nave vai ser desenhada e ele também vai ser o responsável por determinar a relação de seno e cosseno que vai ser multiplicado à aceleração nas fórmulas para que a nave siga em linha reta.

Para a posição e a velocidade serão usados vetores, o motivo é porque a nave tem tanto uma posição no eixo x como no eixo y, e a variação de posição precisa se dar de uma forma específica em cada eixo.

Mas é a aceleração? Por que não seria também um vetor?

A aceleração nesse caso é apenas uma constante de incremento para a velocidade que vai ser multiplicada pelo seno para dar o a variação de velocidade no eixo y e pelo cosseno para o eixo x.


O Modelo matemático fica assim:
 Aceleração(x) = "força" * cos(a)
  Aceleração(y) = "força" * sen(a)


Os comandos funcionam de forma simples:

As setas direita e esquerda aumentam ou diminuem o ângulo da nave, a fazendo girar;

A seta para cima incrementa o produto aceleração e o seno para a velocidade y e do cosseno para a velocidade x.

É preciso levar em conta o limite de velocidade, então esse incremento só pode acontecer caso a velocidade estiver menor que o limite. Após alguns testes eu resolvi que o limite ficaria legal sendo 30x a aceleração angular(depois de multiplicada pelo seno e cosseno), a ideia é que a aceleração só vai ser aplicada caso o módulo de velocidade seja menor que 29x a aceleração angular, pois ela vai poder chegar em 29x - "um valor mínimo qualquer" e vai continuar valendo. Por questões de praticidade, eu prefiro impedir o comando do que corrigir.

Também vou por um fator de desaceleração, ele vai ser uma dissipação de 1/100 de cada velocidade por frame. Isso vai servir pra nave não ficar voando indefinidamente e para corrigir os problemas causados por existir uma velocidade máxima, como a nave ficar presa em determinado ângulo porque a velocidade horizontal ou vertical não abaixa.


O modelo computacional segue neste link

Terceira mecânica:


A terceira mecânica vai ser a habilidade do boss apontar para a minha nave.



Modelo Natural




O modelo matemático é
arc-sen(a) = distância apenas no eixo y / distância total
arc-cos(a) = distância apenas no eixo x / distância total


A ideia aqui é bem simples, eu separo a posição da nave em quadrantes, cada quadrante é de 90 graus da circunferência da nave do chefe de acordo com os padrões de ângulo do processing.




E então, para cada quadrante, eu somo o ângulo do anterior e faço um cálculo usando a distância x ou y e a distância usando a função de arco-seno ou arco-cosseno.

O modelo computacional segue neste link


segunda-feira, 5 de março de 2018

Mami - Aula #1


Bom dia boa tarde boa noite!

Eu sou o Joel, um aluno de Sistemas e Mídias Digitais da UFC, e estou aqui para postar uma série de trabalhos necessários para conquistar a aprovação na cadeira de MAMI(Matemática Aplicada à Multimídia I) e dar orgulho à minha família.

Hoje eu irei realizar o primeiro trabalho, o primeiro passo é assistir o documentário "Hello World! Processing", que vou deixar logo a seguir:

 


O próximo passo é escolher exemplos do site: https://processing.org/examples/

A ideia é alterar o exemplo escolhido a partir das ideias apresentadas no vídeo e fazer alguns comentários, então vou escolher um bem simples sobre variáveis: https://processing.org/examples/variables.html

As variáveis são fundamentais em boa parte dos programas, elas são usadas para guardar determinados tipos de valores: int, float, boolean, dentre outros...

No documentário fala bastante sobre usar o processing para criar padrões através de modelos matemáticos, então eu resolvi alterar o programa do exemplo para fazer um modelo onde os traços fazem zigue-zague.




A ideia foi criar um laço duplo de for onde o primeiro indicaria um determinado ponto no eixo x e o segundo um determinado ponto no eixo y.

Para quem não sabe, o for uma estrutura de laço de repetição composta por 3 partes separadas por ";" :

for(int x=0; x < width; x=x+a)

A primeira parte [ int x=0 ]  é uma variável que vai inicializar o laço, nesse caso eu criei uma variável local, e por ser local, ela só existe enquanto o laço está acontecendo;

A segunda parte [ x < width ] é uma condição que vai ser checada antes do for acontecer, se ela for verdadeira, os comandos dentro do for são executados, se for falsa, o laço é finalizado e o programa segue adiante;

A terceira [ x=x+a ] é um incremento à variável, ele acontece logo após os comandos dentro do for serem executados.

Detalhe: a variável width do próprio processing guarda o valor da largura da janela do programa que está sendo codificado, a variável height guarda a altura, lembre-se delas porque vão ser bem úteis.

O que o primeiro for faz é basicamente checar se a posição x ainda está dentro da tela para então executar o segundo for e fazer o implemento de a, que foi a variável que eu usei para guardar a quantidade de deslocamento que eu quero fazer na horizontal; o segundo for desenha as linhas e então faz o implemento de b, que é a variável usada para o implemento na vertical;

O if é usado para checar se o resto da divisão de x / (2*a) /* sim, o % é usado no lugar do / quando se quer encontrar o resto em vez do resultado da divisão, e isso é bastante útil */ é igual a 0, quando é 0, é porque eu estou em um ponto onde a minha linha vai ser descendente /* \ */ , quando o resultado é a, ou simplesmente quando o resultado não é 0, é porque a linha tem que ser ascendente /* / */, como o resultado sempre vai variar entre 0 e a, eu posso usar essa fórmula para simular essa alternância e definir uma condição para desenhar a linha que eu quero desenhar.

 Os resultados são estes:



a=50 e b=100 :




a=10 e b=10 :





a=200 e b=300 :



Mesmo mudando os valores, as linhas continuam sendo desenhadas, e diferentes valores para as variáveis alteram o resultado final do programa.

Bem, por enquanto é isso, torçam por mim e até a próxima!


Download do arquivo do processing aqui!