sexta-feira, 23 de agosto de 2030

Matemídias, um novo mundo, uma nova jornada


Você dá seus primeiros passos e logo avista
uma pequena criatura verde, com uma aparência mística.
"Olá, estranho!", ela diz.

arte por Dmitry Bolotov - https://www.artstation.com/artwork/OydDxk


Sei que você não é daqui, mas não se assuste, este mundo maravilhoso parece complicado e difícil de entender, mas te garanto que também irá lhe encantar e surpreender. Seja você um mestre ou um aprendiz, este também será um local de aprendizado.

Aqui você encontrará as Tarefas e o Trabalho de um aprendiz meu, Mattheus Del Vianple, produzidos enquanto aprende sobre a antiga arte da Matemática Aplicada a Multimídia. Espero que se encante com sua produção e se inspire a produzir as suas próprias tarefas. Boa leitura!

quinta-feira, 28 de novembro de 2019

Trabalho parte 2 - Super Adriano Lanches Shooter




Parte 2 do trabalho de MAM1 do semestre 2019.2.
O jogo escolhido havia sido Gradius, e a solução visual é uma homenagem à nossa lanchonete e aos Jogos B de Fast Foods. Espero que apreciem.





Link para a pasta contendo Executável e Projeto do jogo:
SALS

segunda-feira, 7 de outubro de 2019

Trabalho parte 1 - Gradius LCD



Apresentação

O jogo que escolhi foi Gradius, pois tenho uma relação de amor e ódio com jogos do estilo shoot'em up e bullet hell. O jogo da empresa Konami foi lançado em 1989, em um período de auge de consoles como o NES da Nintendo e do nascimento de uma nova era de videogames portatéis, movida pelo Gameboy também da Nintendo. No nosso jogo, o jogador deve desviar de tiros de fogo e naves inimigas, atirar lasers e sobreviver a ondas crescentes desses inimigos. A seguir, vamos dissecá-lo em suas submecânicas para apresentá-las.

Submecânicas

Abaixo segue uma série de gifs apresentando visualmente todas as submecâniacas presentes no Gradius:


No GIF acima podemos observar diversas submecânicas:
  • O jogador (nave a esquerda) se movimenta para cima e para baixo.
  • As naves inimigas surgem a direita, se movendo para a esquerda.
  • Pedaços de terra flutuantes (acima e abaixo) surgem nos cantos extremos direitos, se movendo para a esquerda e atirando bolas de fogo aleatoriamente no meio de seu movimento.
  • O jogador pode atirar nos inimigos com lasers.
  • Quando derrota um inimigo, ganha-se pontos

Acima temos as três formas do jogador perder uma vida em uma partida:
  • Ao ser acertado por um Tiro de Fogo.
  • Ao colidir com uma Nave Inimiga.
  • Quando uma Nave Inimiga passa da tela, o jogador perde Force (que seria como a vida dele) e ao atingir zero, ele perde.

Quanto a telas, o jogo possúi quatro:

 Uma tela vazia, o "desligado" do jogo.

 A Tela de Espera, onde o jogador é apresentado a quantidade de vidas e o modo de jogo (que não foi trabalhado pois foi recomendado seguir apenas um modo).

 A Tela de Jogo, onde o jogador interage com o ambiente.

A Tela de Game Over, após perder todas suas vidas. Pode recomeçar o jogo a partir daqui, voltando para a tela de Espera Inicial.

Além de tudo isso, o jogo possui dificuldade dinâmicas, com o passar do tempo na Tela de Jogo o movimento dos inimigos é acelerado gradualmente, também não possui fim, podendo ser jogado enquanto o jogador for capaz de sobreviver.

Modelo Natural

a. Jogador

  • O Jogador pode estar em 5 posições: cima, meio-cima, meio, meio-baixo e baixo, sendo que as posições compostas a nave fica um pouco a frente das outras.
  • O Jogador move a Nave apertando dois botões, um para cima e um para baixo.
  • O Jogador pode atirar um laser em qualquer posição.
  • O Jogador atira apertando um botão de tiro.

b. Naves Inimigas

  • Pode aparecer em 5 posições, idênticas ao do jogador: cima, meio-cima, meio, meio-baixo e baixo.
  • As Naves no meio-cima e meio-baixo começam um pouco antes no eixo horizontal.
  • Elas se movem sempre para a esquerda, três vezes.
  • Quando atingidas pelo laser do jogador, ela é destruída e perde uma vida.
  • Se atingir o Jogador, ele é destruído.
  • Se a nave atravessar a lateral esquerda, o Jogador perde um ponto de força e a nave desaparece.

c. Ilhas Voadoras

  • Aparecem em duas posições, sempre no extremo superior direito ou extremo inferior direito.
  • Se movem sempre para a esquerda, 4 vezes.
  • Após se mover uma vez, a Ilha tem uma chance de atirar um Tiro de Fogo em direção a uma posição fixa, no eixo vertical da nave.
  • Ao atingir a sua última posição, a Ilha desaparece no instante seguinte.

d. Tiro de Fogo

  • Se move para cima quando atirado de baixo e para baixo quando atirado de cima.
  • Se atingir o Jogador, ele perde uma vida.

e. Sistema

  • Conforme o tempo de jogo passa, a velocidade de todos os inimigos aumenta.
  • Cada inimigo destruído, a pontuação aumenta em 20.
  • O jogador começa com três vidas, e ao perder todas ocorre o game over e a pontuação reseta.

Modelo Matemático

Desenhado na ferramenta gratuita https://vectr.com/, elipses pretas representam o Jogador, círculos dourados representam as Naves Inimigas, quadrados vermelhos representam as Ilhas Flutuantes, quadrados laranja representam os Tiros de Fogo e as linhas pretas representam os Lasers.

A imagem acima apresenta todas as possíveis posições para cada objeto de jogo, além de indicar a proporção de nossa tela, que nesse caso será de 20x16. Como desejei trabalhar com módulo para tornar possível a livre alteração do tamanho da tela, foi importantíssimo fazer essa estruturação. Uma observação, neste modelo utilizei valores que variam a partir do 0, então quando citar a posição 3 do modelo, será considera como a 4ª posição visualmente. Vamos então a cada objeto:

a. Jogador

  • Este poderá se movimentar para cima e para baixo no eixo Y a partir da posição 3, de 2 em 2 módulos, até o limite que será a posição 11.
  • Quanto ao eixo X, o Jogador se encontrará na posição 1, com exceção de quando estiver no meio-cima e no meio-baixo, onde estará uma posição a frente, na 2.
  • O tamanho da nave será de 2 módulos de largura e 1 módulo de altura.

b. Nave Inimiga

  • Este poderá iniciar em 5 posições diferentes no eixo Y, todas relativas as possíveis posições do Jogador, ou seja, 3, 5, 7, 9 e 11. Já no eixo X, a nave inicia na posição 12, com exceção do meio-cima e meio-baixo, onde fica na posição 14.
  • A Nave se move apenas horizontalmente, sempre 4 módulos a esquerda.
  • Após se mover 2 vezes, a Nave desaparecerá no terceiro movimento, resultando em algumas possibilidades.
  • Após realizar seu último movimento, se a posição no eixo Y for igual a do Jogador, ele é destruído e perde uma vida.
  • Se atingir nada, reduzirá o nível de Force do Jogador em um ponto.
  • Se a Nave se encontrar na mesma posição em que um laser é atirado, ela será destrúida e retirada do jogo.
  • Ao ser destruída, o Score do Jogador subirá em 20 pontos.

c. Laser

  • É atirado ao apertar o botão de tiro, e sempre aparece na mesma linha onde o Jogador está.
  • Ao ser atirado o Jogador não poderá se mover durante um curto espaço de tempo.
  • É desenhado de forma quebrada mas seguindo uma lógica, será desenhado uma linha de 1 módulo de largura, 0.5 módulo abaixo da posição no eixo Y do Jogador e na posição 3 no eixo X. Uma segunda linha de 3 módulos de largura será desenhada na mesma posição Y mas na posição 5 em X. Outra linha de mesmo tamanho será desenhada na posição 9 e outra será desenhada na posição 13. Mas novamente temos a exceção do meio-cima e meio-baixo, onde todas as posições no eixo X devem ser movidas 2 módulos para a direita.
  • O laser é calculado meticulosamente para não sobrepor nenhum objeto, como no jogo original.

d. Ilhas Flutuantes

  • Estas começam sempre em duas posições, 17 no eixo X em cima ou embaixo, e na posição 0 ou 14 no eixo Y.
  • Novas Ilhas aparecem sempre em locais alternados, uma embaixo, depois em cima, depois embaixo, e assim por diante.
  • Se movem sempre para a esquerda, 4 módulos por vez. Após se moverem 4 vezes, elas desaparecem.
  • Após se mover uma vez, na posição 13 do eixo X, há uma chance de um canhão preso nessa ilha atirar um Tiro de Fogo.

e. Tiro de Fogo

  • Gerado inicialmente na posição 13 do eixo X, e na posição 2 do eixo Y quando atirado de cima ou na posição 12 quando atirado por baixo.
  • Se move sempre para a esquerda, 3 módulos por vez, e se move 2 módulos para baixo se atirado de cima e 2 módulos para cima se atirado de baixo.
  • Desapece após se mover 3 vezes.
  • Se após o terceiro movimento o jogador se encontrar na posição 5 e uma bola de fogo vier por baixo, ou na posição 9 e uma bola de fogo vier por cima, o Jogador é destruído e perde uma vida.

f. Sistema

  • Com o passar do tempo, o jogo vai ficando mais rápido, com todos os inimigos atualizando mais rapidamente.
  • Se o Jogador zerar sua barra de Force, ele é destruído e perde uma vida.
  • O jogador começa com 3 vidas, e ao perder as três, ele perde o jogo e seu Score é zerado.
  • A quantidade de pontos de Force é mostrada em uma barra fragmentada no topo esquerdo da tela.
  • O Score é mostrado na parte inferior esquerda da tela durante a tela de Jogo e a tela de Game Over, no mesmo local também é mostrada a quantidade de vidas, mas apenas durante a tela de Espera.

Modelo Computacional

Para produzir meu port, decidi utilizar a ferramenta Processing com os seguintes pontos a se refletir:
  • É a ferramenta mais utilizada nas aulas de MAM1 e também será utilizada para realizar a prova.
  • Apesar da facilidade de organização e produção de um projeto em ferramentas especializadas em produção de jogos, muitas destas são facilidade pré-programadas que de certa forma podem levar o desenvolvedor a relaxar e a depender da ferramenta, coisa que o Processing não permite.
  • Muitas das funções de ferramentas de produção de jogos já vem pré-codificadas e boa parte da codificação acaba ficando por trás dos panos, deixando o desenvolvedor um pouco distante daquilo que ele está fazendo, utilizando o Processing boa parte das funções devem ser feitas a mão e o esforço de produção é maior e mais controlado.
Lendo isso parece estupidez minha escolher a ferramenta mais difícil, mas como o ambiente da universidade é um ambiente de aprendizado e, como programador, tenho noção de que a escolha de uma linguagem ou ferramenta depende daquilo que se deseja produzir. Como não havia a necessidade de produzir um projeto grande, o Processing me pareceu o suficiente para meu projeto. 

Todo o código está no link abaixo, e, apesar de estar completamente funcional, tem diversas coisas que adoraria ter tido mais tempo de organizar, além de ter desejado me utilizar mais de POO, porém ainda não tivemos aulas sobre o assunto e não tive tempo de estudar por fora. Contudo, o processo de produção desse trabalho foi muito divertido, apesar da quantidade massiva de tarefas que disputavam com meu tempo de produção do projeto ter me deixado fadigado muitas vezes.

Link para o código: Trabalho MAM1.

sábado, 5 de outubro de 2019

Tarefa 7 - Mapeamento de dados e bolinhas fantasmas

"empregando as funções dist e map do Processing, explicar e
exemplificar como a posição do mouse, numa janela com
proporção 4:3, pode mover um círculo no interior de um retângulo com proporção 16:9 centralizado na tela"

Algo que podemos acabar não percebendo, mas nossos mouses passam por um processo de mapeamento. Imagine uma apresentação onde a tela de exibição é do tamanho de uma de cinema, apesar do tamanho excessivo da tela, a quantidade de movimento do mouse se mantém a mesma, graças a esse mapeamento.

O processo de mapeamento é uma tarefa bem simples. Foi utilizado o ponto 0,0 da tela como ponto central de referência para tudo.
Para mover a bolinha, é necessário sabermos as distâncias horizontais e verticais do ponto central até o ponto do mouse. A própria posição X e Y do mouse serão usadas para definir essa distância.

Os limites da própria tela serão os limites da posição do nosso mouse. Assim:
  • Distância X mínima = 0;
  • Distância Y mínima = 0;
  • Distância X máxima = Largura da Tela;
  • Distância Y máxima = Altura da Tela.
As posições da bolinha são relativas a posição do ponto de criação do retângulo, como decidi deixar a caixa centralizada na tela, os pontos serão:
  • Distância bola X mínima = Metade da Largura subtraído de metade da Largura da Caixa;
  • Distância bola Y mínima = Metade da Altura subtraído de metade da Altura da Caixa;
  • Distância bola X máxima = Metade da Largura somada de metade da Largura da Caixa;
  • Distância bola Y máxima = Metade da Altura somada de metade da Altura da Caixa.


Agora já temos todos os valores necessários para nosso mapeamento.

Aqui temos todo o processo de mapeamento.


A distância atual do mouse até o ponto 0,0 foi colocada em proporção com as distância totais da Tela e as distâncias totais da Caixa. Assim garantimos o movimento controlado de nossa bola.

Código em Processing: Tarefa 7.

domingo, 15 de setembro de 2019

Tarefa 6 - Ao infinito e além do Yin Yang

"crie uma função recursiva que crie o efeito do yin yang infinito, dando atenção ao controle do limite, e discuta a implementação de um zoom para seu programa"

obs: Pedi para o professor Melo para que pudesse publicar minha tarefa do yin yang no lugar da tarefa de fibonacci, pois ela já estava quase completa no dia em que foi postada na pasta do drive.

Yin Yang, equilíbrio não apenas na imagem, mas na forma e na proporção. E uma das mais comuns tatuagens hoje em dia.

Para chegar ao resultado desejado, foi necessário um estudo do uso de funções recursivas, que ainda não havia sido estudada em Programação II. Mas a lógica do Yin Yang infinito independe do nosso conhecimento de programação. Vamos a ela.

O que há de comum na estrutura deste desenho aparentemente confuso? Apenas uma mente em pleno equilíbrio pode responder.

Temos acima um círculo que dentro de si contém dois círculos. Cada um desses círculos menores conterá outros dois círculos dentro de cada um deles. E cada um desses círculos menores ainda possuirão outros dois círculos em seu interior. É logo perceptível a presença de uma progressão definida na geração de nossa imagem:
1 -> 2 -> 4 -> 8 -> 16 -> infinito...
É possível então escolhermos a quantidade de círculos que desejamos desenhados na tela, em uma função que dentro dela: desenhará um círculo e em seguida chamará a si mesma para desenhar outros dois círculos menores em posições relativas ao seu centro atual.

A produção dos símbolos é um tanto quanto complexa, é necessário levar em consideração a variação de cor entre preto e branco e se o novo círculo ficará em cima ou em baixo. Talvez no futuro quando tiver estudado mais programação eu consiga "limpar" esse código e torná-lo mais curto.

O parâmetro control é importantíssimo para controlarmos a parada da produção de nossos círculos. Sem ele nossa função se tornará infinita e o processing entrará em pane. Introduzimos na chamada da função a quantidade de camadas que desejamos que nosso yin yang tenha pelo control.

Para gerar um efeito de zoom, foi necessário apenas aumentar geometricamente o valor do diâmetro. É importante frisar a importância desse aumento ser geométrico, pois se for feito por progressão aritmética, a velocidade do zoom diminuirá a cada segundo, pois o aumento não será proporcional a redução de tamanho que os círculos seguem, pois eles seguem uma P.G. de razão fracionária.

Um aumento de apenas 1% parece pouca coisa, mas é importante lembrar que o processing roda a 60 FPS, então esse aumento seria superior a 60% por segundo (aproximadamente 80%).

Essa talvez tenha sido a tarefa mais divertida até agora, o uso de recursividade pode ser um tanto desafiador e estressante, mas os resultados aplicados a computação gráfica são belíssimos.

Código em Processing: Tarefa 6.

Tarefa 5 - Ouviram do Ipiranga ás aulas práticas

"discutir o emprego das instruções quad, beginShape e endShape,
rectMode e ellipseMode do Processing na construção da
bandeira do Brasil, considerando a Lei Federal No 5.700"

Olhando assim nem parece que utiliza décimos de módulo para ser desenhada. Nessa tarefa, vamos focar no quadrado, no losango e no círculo da bandeira, como pedido.

Analisando a referência do processing sobre as funções rectMode() e ellipseMode() é possível perceber uma similaridade entre as duas, são ambas usadas para redefinir o modo como os parâmetros das funções rect() e ellipse() devem ser interpretados.

Para esse trabalho, decidi utilizar o rectMode(CENTER), que faz com que o ponto (x,y) inicial do quadrado seja calculado a partir do centro dele. O ponto x e o ponto y estarão, respectivamente, no x central menos metade da largura e no y central menos metade da altura, como mostra na figura abaixo.

Para o círculo, utilizei o ellipseMode(RADIUS), que modifica os parâmetros de altura e largura da ellipse para meia largura e meia altura, como se mudasse de diâmetro para raio. Fiz isso para adaptar a lei 5700, que apresenta as proporções do círculo pelo raio.

Como dito acima, a lei indica que o círculo azul terá raio de três módulos e meio, então achei importante alterar o modo como a função funciona.


Para a produção do losango, há duas opções. Uma utilizando a função quad() e outra utilizando as funções beginShape(), endShape e vertex(). Ambas as opções precisarão das mesmas coisas, a posição de cada vértice do losango na tela. Porém, há uma diferença importante entre as duas.

Enquanto o quad() recebe como parâmetros os quatro pontos do losango e fecha a figura, beginShape()/endShape() precisaria de cinco pontos para formar uma figura fechada. Esse quinto ponto seria o próprio ponto inicial da figura, que servirá também como ponto final e de fechamento. Essa segunda forma de desenhar o losango possui uma imensa liberdade de uso e com ela podemos desenhar formas bastante peculiares, mas que não vem ao caso de nossa tarefa. Fechar a figura será apenas necessário quando formos fazer uso de contornos.

Nossa bandeira é mais complexa de se produzir e calcular do que as bandeiras do Japão e da Suíça, e talvez por isso para muitos ela seja um símbolo de beleza tão profunda.

Após isso é apenas uma questão de codificar, tendo sempre o modelo acima como referência na hora de criar nossas funções.

Código em Processing: Tarefa 5.


quinta-feira, 12 de setembro de 2019

Tarefa 4 - Um arremesso e tanto

"adicionar a visualização, diretamente na janela do simulador
de lançamento balístico, de todos os valores das variáveis
envolvidas, incluindo as velocidades instantâneas horizontal e vertical, discutindo como as mesmas foram obtidas"

Worms, jogo com alguns dos mais incríveis feitos balísticos da humanidade, também nos mostram o potencial auto-destrutivo de qualquer pequena falha em um cálculo.
Adicionar uma visualização das variáveis a janela foi uma tarefa simples, precisei apenas utilizar um retângulo como fundo para que as linhas não atrapalhassem a leitura e garantir que o tamanho da variável escrita não ultrapasse uma casa decimal.

Aqui nossa bolinha está com aceleração tanto horizontal quanto vertical. Ela inicia com velocidade horizontal positiva e vertical negativa, mas aos poucos esses sentidos irão inverter, devido a aceleração. Por fim, a bolinha sumiria a esquerda.

A velocidade atual é algo fácil de se obter. Segundo a clássica fórmula física v = v0 + a.t, teremos que a velocidade atual é calculada em função da velocidade inicial, da aceleração e do tempo. Temos essas três variáveis em nosso programa, então:
É necessário calcular a aceleração de cada direção separadamente, pois não estamos trabalhando com velocidade vetorial e bidimensional, mas com uma composição desta unidimensionalmente.

Assim, temos nossa visualização de variáveis e nossas velocidades atuais!
Código em Processing: Tarefa 4