Blog destinado ao curso Sistemas e Mídias Digitais - SMD

  • DOUGLAS SILVA ART

    Curta a minha página no Facebook

  • THE CHIBIMAKERS

    Curta também a página do grupo The chibimakers, no qual postamos sempre desenhos no estilo Chibi.

segunda-feira, 23 de outubro de 2017

Atividade 13 - MAMI

A atividade era criar um jogo seguindo as seguintes características:



Para essa atividade eu usei os seguintes sprites, ambos do jogo Castlevania - Symphony of the Night:




Criei duas variáveis, x e y, que são a posição do canto superior esquerdo do retângulo que representa o personagem. Carreguei os sprites usando o loadImage() no setup.

Criei uma função chamada jump(), que verifica se o personagem está pulando ou não através da variável jumping. Para que isso aconteça, usei a "função MRU” de um exercício anterior. Criei uma variável tempo, que multiplicando com -0.5 faz o pulo desacelerar.

Criei uma função chamada enemy(). Dentro dela há uma elipse (que representa o inimigo em sí) e duas variáveis, inimigoX e inimigoY, que corresponde a posição central da elipse. A cada frame decremento -4 ao inimigoX, fazendo com que ele se desloque para a esquerda. Quando essa variável for menor que 0, o inimigo volta para a posição inicial.

A função colision() faz o bounding box entre o personagem e o inimigo, e quando o personagem colide diminui a variável chamada chances.

Criei também a função walk(). Quando o estado da variável movendo for igual a "DIREITA”, a variável x será incrementada, e quando for igual a "ESQUERDA", x será decrementado.

Na função keyPressed, quando é clicada a seta esquerda ou a direita, altera-se a direção do personagem. Já na função keyReleased ela faz com que o personagem volte ao estado parado quando as teclas não estão sendo pressionadas.


A função gameover() serve para testar se o jogador perdeu por falta de chances, ou se ele ganhou atravessando a fase toda. Isso tudo é feito com a ajuda das variáveis gameover e ganhou, que se tornam true ou false dependendo do que acontecer.



Se você quiser ver como foi feito, basta clicar aqui para baixar o código do projeto.
Share:

Trabalho Final MAMI - Pt 1

O trabalho final da disciplina de Matemática Aplicada à Multimídia I (MAMI) é um gerador automático de arte. Esse gerador deve levar em conta 3 ou mais obras de uma serie de um artista, e criar um programa capaz de reproduzir variações originais de tais obras.

Modelo Natural
Foto tirada na casa da artista



Artista escolhida:


Karina Paula é uma designer gráfica cearence, nascida em 1995. Um de seus trabalhos como designer foi criar uma série de quadros focados em formas geométricas, com influência no movimento da vanguarda moderna holandesa conhecido como De Stijl (ou Neoplasticismo).

Analisando a série, da obra C-03 até C-05, podemos perceber algumas características:

Obras originais
Características analisadas:
  • 2 linhas diagonais, ou 2 linhas, sendo uma na vertical e a outra na horizontal;
  • 1 circulo central, seguido de um anel ao redor do circulo;
  • 2 à 4 blocos, compostos por quadrados divididos em “triângulos” de cores diferentes;
  • 4 arcos de círculos, compostos por cor chapada ou compostos por um arco de círculo e um arco de “anel” ao redor, dispostos nos quatro cantos do quadro, que possui forma quadrática;
  • 3 cores principais (vermelho, azul e amarelo), e duas de base (preto e branco); 
Formas:
  • Os quadros analisados possuem as dimensões de um quadrado;
  • Dentro do quadrado, existem elementos como: círculos, anéis, quadrados, triângulos e arcos.
  • No centro de cada quadro, há um círculo seguido de um anel ao seu redor.
  • Ainda na parte central, há a presença de blocos. Esses blocos podem variar de 2 à 4 blocos. Cada bloco pode ser formado por um quadrado, ou por dois triângulos de cores distintas;
  • Cada quadro possui nos seus 4 cantos arcos de círculos, que podem vir seguidos de arcos de anéis;
Cores:
  • As cores são compostas sempre por uma cor mais forte e viva, e outra que é a cor preta, geralmente usada para gerar contraste. Além do branco que está presente em todas as obras escolhidas como cor de fundo.
  • Abaixo a paleta de cores das obras escolhida



Modelo Matemático
  • A largura e a altura da tela é de 600x600px. A partir daí é feito um módulo, que eu chamei de A = altura da tela/6. 
Figura 01

Figura 02
  • Como é mostrado nas figuras acima, os círculos centrais são posicionados no centro da tela. Primeiro um círculo menor, que tem a altura de um módulo A. Depois um outro por de trás dele, que tem a altura de A + 35% do módulo. Em seguida outro círculo, com altura A + 70% do módulo, e por último um círculo com altura de 2 * A.
  • Em seguida vem as linhas, que tem a espessura de A/4.
  • Depois os blocos são feitos com largura e altura de 2 * A.
  • Já o primeiro arco dos conjuntos dos arcos, é feito com tamanho de A - 30% de um módulo. O segundo arco que vem por baixo do primeiro é construído com tamanho de A - 15% do módulo. E o último com o tamanho de A.
Modelo Computacional:

Primeiramente, eu comecei criando as variáveis que possibilitarão que aconteça a geração automática de artes. Criei as variáveis: 

  • int linhas: define o tipo de orientação das linhas. Se será horizontal e vertical ou diagonais.
  • int corSelect: define a cor principal da obra, entre vermelho, azul e amarelo.
  • int quantBlocos: define a quantidade de blocos da obra entre 2 à 4.
  • int tipoBloco: define se o bloco será formado por um quadrado ou dois triângulos.
  • int tipoArco: define a quantidade de arcos entre com ou sem anéis.
  • int numArcos: define a quantidade de arcos coloridos ou com uma cor só (que eu também chamo de arco chapado).
Depois eu comecei a construir a estrutura do quadro conforme as Figuras 01 e 02 mostraram anteriormente. Então eu criei uma função chamada middleCircles( ), que desenhas os círculos da parte central do quadro, usando dentro um fill( ) para cada um dos 4 círculos que formam essa parte, pois como pudemos notar, são 4 círculos, sendo o interno colorido ou preto, o segundo que fica envolto do primeiro é sempre branco, o próximo pode ser colorido ou preto, e o ultimo também será sempre branco. No fill( ) de cada um é passado os 3 arrays de cores chamados red, green e blue, no qual dentro deles tem um outro array chamado colorTones. O propósito do colorTones é fazer com que as cores sejam geradas de acordo com a função cretePallete( ), que vou explicar mais para frente.

Fiz também a função drawLine( ), que de acordo com a orientação que é passada através da variável global linhas, dá a orientação horizontal/vertical ou diagonal. Tudo isso é feito dentro de um switch( ), e caso for 0 (horizontal/vertical), as linhas são desenhadas com a função rect( ). Caso seja 1 (diagonal), são desenhadas com a função quad( ).

E, seguida eu construi os blocos. Primeiro eu fiz as funções firstSquare( ), secondSquare( ), thirdSquare( ) e fourthSquare( ), que criam os quadrados a partir de dois triângulos, como também foi explicado visualmente nas Figuras 01 e 02. Depois eu crio um função chamada drawBlocks( ), que chama as funções anteriormente citadas de acordo com a quantidade de blocos que for sorteada na variável quantBlocos. Variando assim de 2 à 4 blocos que serão gerados. Contudo, a drawBlocks só é chamada dentro da função createBlocks( ), que recebe dois valores inteiros. Um é a orientação da linha, e o outro é a quantidade de blocos. Se a orientação for referente a horizontal/vertical, e a quantidade de blocos for referente a dois, então a orientação passa a ser na diagonal e então é chamada as funções drawBlocks( ) e drawLines( ). Agora se não for, então elas são chamadas normalmente.

Para construir os arcos, também fiz quatro funções separadas: firstArc( ), secondArc( ), thirdArc( ) e fourthArc( ). Elas criam 3 arcos com a função arc( ), e fill( ), que também segue o mesmo princípio dos círculos. Só que ele são desenhados através da função drawArc( ), que recebe um parâmetro, que nesse caso é a variável global numArcos, e desenha de acordo com os casos: se for 0, desenha quatro arcos coloridos (intenda por coloridos um arco menor formado por uma cor colorida, o do meio branco e o externo também colorido), se for 1 desenha dois arcos coloridos e dois chapados(todos os arcos são da mesma cor), e se for 2 apenas um arcos é colorido e os outros 3 são chapados.

Já a função createPallete( ), é gerada de acordo com a cor principal selecionada, que é armazenada na variável global corSelect. A partir daí, caso seja 1, a cor principal será vermelha, caso seja 2 será azul e caso seja 3 será amarela. Contudo, em cada caso, são armazenadas nas posições 0 dos arrays red, green e blue, os valores referentes as cores vermelha, azul ou amarela, e nas posições 1 e 2 as cores branca e preta respectivamente. Gerando assim uma paleta.

Agora, na função randomizeTones( ), é onde será atribuído as cores da paleta aos arrays colorTones e arcTones, que será de acordo com o padrão de cores que tem nas obras originais. Sendo elas: 

  • se o circulo central interno for colorido,  o central externo é preto, e vice-versa;
  • se um triângulo do bloco for preto, o outro será colorido e vice-versa;
  • se os arco interno for colorido, o externo é preto e vice-versa;
  • os arcos podem ser todos de uma cor, sendo todos coloridos ou tpretos;

Por ultimo eu chamo as funções no setup, e cada vez que abrir o programa, é gerado uma obra diferente.

Resultados do programa:







Se você quiser ver como foi feito, basta clicar aqui para baixar o código do projeto.




Share:

Atividade 12 - MAMI

A atividade era pra desenvolver e explicar uma aplicação que apresenta um mapa isométrico com base em dois tiles à sua escolha 

Eu resolvi escolher 3 tiles, para poder gerar um mapa mais interessante.


Primeiro criei as variáveis PImage que guardarão as imagens e defino-as no setup(). Após isso, criei uma matriz chamada mapa, que organiza e recebe a posição de cada tilaste que será mostrado na tela.

Em seguida criei uma função chamada mapa (), que realmente vai desenhar o mapa. Nela dois laços for() percorrerão todas as posições da matriz. Dentro dos laços, há um switch() para saber o valor de cada posição e desenhar o tileset correspondente. 



Os tiles possuem o tamanho da metade da largura igual a 50 e da metade da altura igual a 25, sendo que para posicioná-los na tela, eu uso 350-i*50+j*50 (para o eixo x), e 50+i*25+j*25 (para o eixo y), no qual o 350 é para posicionar na metade da tela. No eixo x, o “i” serve para decidir a posição x inicial do primeiro tile e o ”j” para ajudar a posicionar os demais. Já no eixo y, o “i” serve para ajudar o “j” a determinar a posição y.


Se você quiser ver como foi feito, basta clicar aqui para baixar o código do projeto.
Share:

Atividade 11 - MAMI

A atividade seguinte consiste em reimplementar a máquina de estados finitos anterior (feita na sala de aula), substituindo a variável keyPressed pela função keyPressed () e explicando suas diferenças de uso, vantagens e desvantagens.

A máquina de estados tem 3 estados: PARADO, ANDANDO e MARTELANDO, equivalente aos números 0, 1 e 2 respectivamente. No setup() eu carrego as imagens dos 3 estados usando o loadImage().
Estados: PARADO, ANDANDO e MARTELANDO

Em seguida no draw (), eu declaro as funções:  mostraMario (), passando a variável estadoMario como parâmetro e a função estadoMario().

Na função mostraMario() é onde será verificado qual estado do Mario está sendo processado no momento. Daí então ele mudará o sprite dele de acordo com o estado, que é verificado na função keyPressed (). Nela, caso a tecla LEFT seja apertada, a variável estadoMario recebe o estado ANDANDO. Caso seja a tecla barra de espaço, ela recebe a variável MARTELANDO. Na função estadoMario(), é verificado se o estado ANDANDO ou MARTELANDO estão sendo acionados. Se estiverem, uma variável global chamada tempo é incrementada, e se ela ultrapassar 30 segundos, ela zera, e a variável estadoMario volta a ser PARADO.

keyPressed VS keyPressed()
keyPressed:
A variável do sistema booleano keyPressed é verdadeira se qualquer tecla for pressionada e falso se nenhuma tecla for pressionada. O fato dela ser uma variável é bom porque ela pode ser utilizada em mais de um local. Contudo, por ela ser só uma variável, é preciso implementar toda a lógica da máquina de estados usando-a.

keyPressed():
A função keyPressed () é chamada cada vez que uma tecla é pressionada. Por causa de como os sistemas operacionais suportam repetições de teclas, manter pressionada uma tecla pode causar várias chamadas para keyPressed (). A taxa de repetição é definida pelo sistema operacional e pode ser configurada de forma diferente em cada computador. Em compensação, essa função já funciona como uma máquina de estados, melhorando o seu código.

Se você quiser ver como foi feito, basta clicar aqui para baixar o código do projeto.
Share:

sexta-feira, 20 de outubro de 2017

Atividade 10 - MAMI

A atividade era explicar como se pode detectar cliques do mouse sobre um botão retangular com cantos arredondados.

Primeiro ei fiz o modelo do botão. Para isso ele vai ter 4 círculos nos seus cantos e o preenchimento do botão será dois retângulos, sendo que o primeiro retângulos possui largura maior que o segundo, e o segundo possui altura maior que o primeiro, como na figura abaixo. Os círculos deverão ser criados nos pontos em que há intersecção dos retângulos, para que assim se forme um botão retangular com cantos arredondadas.


Depois eu criei duas funções. A primeira faz o calcula da distância, recebendo dois valores (A e B) e retornando a diferença entre eles. Eu chamei ela de distancia1D( ). Usei a função abs( ) para o valor sempre ser positivo. A outra faz o calculo da distância entre dois pontos, recebendo os valores x1, y1, x2, y2 e retornando o calculo da equação: d = √( (x2 - x1)² + (y2 - y1)² ). Eu chamei ela de distancia2D( ). Vale lembrar que a função distancia2D( ) chama a função distancia1D( ) para poder fazer o calculo da diferença entre os valores.

Em seguida, eu criei os círculos e retângulos no draw( ), usando as funções ellipse( ) e a rectMode(RADIUS), para facilitar na hora de fazer as comparações que serão necessárias posteriormente.



Também criei a função mousePressed(), que checa se o botão está sendo clicado. Para isso, eu criei duas variáveis locais chamadas distX e distY, que recebem respectivamente o valor do calculo da distancia (através da função distancia1D) entre os valores x e y correspondentes aos retângulos do botão e as posições do mouse (mouseX e mouseY). Somente assim eu consigo verificar se o mouse estará clicando dentro da área correspondente a parte retangular do botão. A mesma verificação é feita para os 4 círculos que estão nos cantos do botão, só que para isso eu uso o calculo da função distancia2D, e comparo com as posições do mouse(mouseX e mouseY). Se estiver clicando dentro da área do botão, então a cor do background muda pra ciano. Se não estiver clicando, ela continuará cinza.



Se você quiser ver como foi feito, basta clicar aqui para baixar o código do projeto.
Share:

Atividade 09 - MAMI

O bounding boxe é uma técnica usada para se detectar a colisão de dois ou mais objetos(ou sprites), no qual os mesmos passam a ser considerados como caixas(retângulos), para se facilitar o cálculo. Como na imagem abaixo, no qual a área correspondente a bolinha e ao quadrado que está inclinado se transforma em duas caixas invisíveis.

Para explicar melhor a técnica de detecção de colisão por bounding box, eu desenvolvi uma versão simplificada do jogo Breakout, que considera a colisão de toda bola com o bastão e com dois ou mais obstáculos. 

Primeiro eu criei a função bastao(), que cria e faz movimentar o bastão que fica na parte inferior da tela. Ela recebe como parâmetro a posição x do bastão. Dentro dela, desenho um retângulo com a posição x indicada pelo parâmetro da função e a posição y recebe um valor de 580px, para que o bastão fique na parte de baixo da tela mais não colada ao fim da tela. Após isso, verifico se alguma tecla foi pressionada, caso a tela RIGHT tenha sido pressionada, incremento mais 5 na variável da posição x. Também verifico se o bastão está ultrapassando a largura da tela. Se a variável x for menor que o width da tela menos 100(o tamanho do bastão no eixo X), então é incrementado 5 à variável bastãoX. O mesmo é feito para o lado esquerdo.

Depois eu criei uma função chamada bola(), que recebe dois parâmetros, x e y. Dentro dessa função, usando esses parâmetros eu desenho uma bola com a função ellipse(). Em seguida, eu faço verificações para quando a bolinha bater nas paredes laterais, em cima e no bastão. Se colidir, ela inverte a sua direção. 

Também criei uma função chamada colisao(), que verifica se a bola colidiu com cada um dos 3 obstáculos que eu criei como variáveis globais. Também criei 3 variáveis do tipo booleano, chamadas de obsDestroyed 1, 2 e 3, que armazenam o estado dos obstáculos(no caso elas são armazenadas inicialmente como false). Se a bola tiver colidido com algum dos obstáculos, então é mudado o valor dessas variáveis para true, possibilitando assim que os obstáculos sejam destruídos. Mas eles só serão destruídos de fato na função destroi(), que verifica se as variáveis obsDestroyed 1, 2 e 3 são true. Se forem, então os obstáculos são criados. Se forem false, então os obstáculos passam a não existir.




Há também uma função chamada gameover(), que verifica caso a bola ultrapassa a altura inferior da tela, parando assim o jogo para, as configurações do jogo volta para a inicial e é dada uma mensagem de “GAME OVER” na tela.

No draw(), eu chamo as funções bastao(), passando o valor bastaoX, que é uma variável global, a função bola(), com os seus valores bolaX e bolaY, que também são variáveis globais, e as funções colisao(), gameover() e destroi().


Se você quiser ver como foi feito, basta clicar aqui para baixar o código do projeto.

Share:

quinta-feira, 12 de outubro de 2017

Atividade 08 - MAMI


Para a criação da função moveCaixa2(x1, y1, x2, y2, n), que realiza o movimento interpolado de um quadrado de lado 10 pixels, entre (x1, y1) e (x2, y2), em n passos, eu fiz o seguinte:

Primeiro eu defini uma variável (i) para ficar responsável pelo movimento.

Depois criei a função moveCaixa2( ), que recebe os parâmetros da posições iniciais x1 e y1, das posições finais x2, y2, e a quantidade de passos n. Dentro dela, eu faço o calculo da diferença entre as distancias x2 - x1, e y2 - y1, e armazeno o valor em duas variáveis chamadas respectivamente de distx e disty. Em seguida, eu verifico se a variável i é menor ou igual a 1, caso seja, o movimento pode ser executado, desenhando assim o retângulo com a função rect(), onde sua posição x é a posição x inicial (x1) mais o produto de i com a diferença do x final com o x inicial (distx), sua posição y é a posição y inicial (y1) mais o produto de i com a diferença de y final com y inicial (disty). Sua altura e largura eu defini com 10px.

Após o quadrado ser desenhado, incremento à variável i o valor dela mesma mais a divisão de 1 pela quantidade de passos (n).


Por fim, na função draw( ) apenas defino o background como preto e chamei a função moveCaixa2( ).


Se você quiser ver como foi feito, basta clicar aqui para baixar o código do projeto.

Share:

Trabalho Final MAMI - Pt 2

Nessa segunda e última parte do Trabalho Final da cadeira de MAMI, eu apenas coloquei uma interface gráfica com a ajuda da biblioteca Cont...