Matemática Aplicada à Multimídia I - 2019.2 - Aleksandr
quarta-feira, 4 de dezembro de 2019
terça-feira, 19 de novembro de 2019
Atividade 12 - MEF 2

Utilizando a definição da Wikipédia, o conceito de Máquina de Estado Finita é concebido como uma máquina abstrata que deve estar em um de um número finito de estados. A máquina está em apenas um estado por vez, este estado é chamado de estado atual. Uma transição indica uma mudança de estado e é descrita por uma condição que precisa ser realizada para que a transição para outro estado ocorra.
No caso da tarefa pedida, a maquina de estado é utilizada para saber o estado atual do personagem e assim sincronizar a realização do movimento com a imagem que representa o estado do personagem, no caso se ele deve ir para a direita, o movimento deve ser feito para esse lado e a imagem deve mostrá-lo olhando para a direita.
A dificuldade que tive ao fazer essa código foi o fato de que, ao pressionar o botão, o personagem se movimentava várias casas ao mesmo tempo. Para solucionar isso usei um sistema de flag, onde, quando a tecla era pressionada, a variável de controle era verdadeira e a ação de andar só seria feita em um espaço por pressionar de botão.
Atividade 11 - Máquina de Estados Finita
O objetivo desta atividade é reimplementar a máquina de estados já criada, substituindo a variável keyPressed pela função keyPressed(), explicando as diferenças de uso, vantagens e desvantagens.
Link do código: https://drive.google.com/open?id=0B3-iqp7LYuNJZk83Q0F0UlExX2M
Primeiramente, é importante estabelecer as diferenças entre a variável booleana keyPressed e a própria função keyPressed(). No caso da variável, podemos inseri-la em qualquer função do nosso programa como um elemento pontual, tornando-o mais extenso por causa de verificação true ou false, porém mais prático se houverem poucas instâncias.
No entanto, ao optar pela função keyPressed(), podemos criar uma única variável booleana (verificador) no começo do código, e depois apenas coordenar as ações com o verificador, as ferramentas "keyCode" e "key" e a função keyReleased(). Dessa forma, podemos inserir várias ações sem prejudicar a legibilidade do código.
No código da Máquina de Estados criada, foram criadas armazenadores de imagem pelo PImage, e constantes "final int" para os Estados. Por padrão, o Estado irá ser "parado" e o tempo será 0. No "void setup" são carregadas as imagens.
No "void draw" são colocadas as funções criadas processaEstados(), mostraMario(estadoMario) e println(estadoMario, tempo), este último para indicar o tempo em que a ação está sendo realizada e o número do Estado (0 = parado, 1 = andando, 2= martelada).
No processaEstados() são usados testes booleanos para mudanças dos estados, no mostraMario exibem-se as imagens de acordo com o Estado atual e na função keyPressed() verifica-se as teclas pressionadas e muda-se o estadoMario até que se solte a tecla.
Link do código: https://drive.google.com/open?id=0B3-iqp7LYuNJZk83Q0F0UlExX2M
Atividade 10 - Tilesets
Para criar o mapa desejado, utilizei os dois tiles abaixo.
No programa primeiro iniciei as variáveis PImage, que guardam as informações das imagens escolhidas.
Depois fiz uma matriz que mapeia as imagens dos tiles de acordo com o número dado na função que será implementada posteriormente, no comando switch.
Então, fiz uma função que lê a matriz e carrega a imagem de acordo com a numeração dada pelo comando switch em cada posição. Caso seja 0, carrega a imagem da grama, se for 1, carrega a imagem da água. Para a imagem não ficar muito grande, fiz os espaçamentos horizontais entre as unidades serem de 60 pixels, e os verticais, de 30 pixels. O resultado pode ser verificado abaixo:
O conceito de Tesselação (do latim tessellae) é o recobrimento de superfícies bidimensionais (planos) com unidades básicas sendo polígonos congruentes ou não, de forma que não existam espaços entre eles e de modo que a superfície total seja igual à área recoberta.
Isso é exatamente o que ocorre com os cenários de um jogo 2D, há uma área fixa que é recoberta por unidades, os tiles, sem que haja nenhum espaço, para dar a sensação de continuidade e aprimorar a experiência do jogador.
Atividade 9 - Pong
Nesta tarefa, devemos explicar e exemplificar a diferença entre o uso da variável de sistema keyPressed e a função keyPressed() com base no desenvolvimento de uma versão simplificada do jogo Pong, que considere a colisão do centro da bola com o bastão e com dois ou mais obstáculos.
Para isso, desenvolvi uma versão do jogo Pong, que inicia com uma tela que solicita ao usuário para apertar um botão para começar o jogo:
Criei uma variável booleana chamada tela, que quando verdadeira cria esta página. Quando o 'espaço' é pressionado, o booleano tela fica falso, iniciando o jogo:
Para isso, desenvolvi uma versão do jogo Pong, que inicia com uma tela que solicita ao usuário para apertar um botão para começar o jogo:
![]() |
| Tela inicial. |
Criei uma variável booleana chamada tela, que quando verdadeira cria esta página. Quando o 'espaço' é pressionado, o booleano tela fica falso, iniciando o jogo:
void keyPressed() {
if(keyCode == 32) {
tela = false;
}
if(tela == false && keyCode == 82) {
tela = true;
// reset
barraX = (width/2)-(larguraB/2);
bolaX = 15;
bolaY = 100;
}
}
Foi usada a função keyPressed() para verificar se o botão correto foi pressionado e realizar a ação;
A diferença entre a função keyPressed() e a variável keyPressed, é que nesta última ela pode ser usada em um if para verificar se um botão foi pressionado, baseado em um keyCode.
Já na função é possível fazer isto de maneira automática, sem a necessidade de um if, pois ao criar a função já está se assumindo que um botão foi pressionado.
O usuário pode vencer ou perder. Na tela principal existem duas caixas em que a bola deve colidir. Caso a bola ultrapasse o "chão" é apresentada uma tela que informa que o usuário perdeu a partida, mas que pode reiniciá-la ao apertar o botão 'R'.
Para calcular a distância entre a bola e as caixas foi usada esta função:
float distancia(float x1, float y1, float x2, float y2) {
float b, c;
b = abs(x1 - x2) * abs(x1 - x2);
c = abs(y1 - y2) * abs(y1 - y2);
float a = sqrt(b + c);
return a;
}
Para organizar melhor o código, decidi implementar cada funcionalidade separadamente. No draw() elas são chamadas após o usuário iniciar o jogo:
if(tela) {
background(29, 212, 216);
fill(255);
textSize(15);
text("APERTE 'ESPAÇO' PARA COMEÇAR", 25, height/2);
stroke(255);
line(20, (height/2)+20, width-30, (height/2)+20);
line(50, (height/2)+35, width-65, (height/2)+35);
}
else {
background(255, 193, 7);
colisaoBola();
ellipse(bolaX, bolaY, raio, raio);
colisaoBarra();
rect(barraX, height-alturaB, larguraB, alturaB);
colisaoSprites();
}
Caso as duas caixas sejam eliminadas e a bola não caia no chão, o usuário vence a partida.
A colisão da bola foi implementada nesta função:
void colisaoBola() {
bolaX += velX;
bolaY += velY;
// paredes
if((bolaX > width-(raio/2)) || (bolaX < 0+(raio/2))) {
velX = -velX;
}
if(bolaY < 0+(raio/2)) {
velY = -velY;
}
// barra
if((bolaX + raio/2 >= barraX) && (bolaX - raio/2 <= barraX + larguraB) &&
(bolaY + raio/2 >= height - alturaB) && (bolaY + raio/2 <= height)) {
velY = -velY;
}
// caso caia no chão
if(bolaY > height) {
background(255, 87, 34);
textSize(19);
fill(255);
stroke(255);
text("VOCÊ PERDEU!", width/2 - 70, height/2-25);
line(25, height/2-7, width-28, height/2-7);
text ("APERTE 'R' PARA REINICIAR", 25, height/2+25);
}
}
Ao apertar o botão 'R' todos os valores iniciais são "resetados", ou seja, seus valores atuais são atualizados como iniciais. Assim, foi possível reiniciar o game.
![]() |
| O usuário pode perder a partida caso a bola ultrapasse o limite inferior da tela. |
Para calcular a distância entre a bola e as caixas foi usada esta função:
float distancia(float x1, float y1, float x2, float y2) {
float b, c;
b = abs(x1 - x2) * abs(x1 - x2);
c = abs(y1 - y2) * abs(y1 - y2);
float a = sqrt(b + c);
return a;
}
![]() |
| Caso o usuário deixe a bola cair e perca a partida, esta tela é apresentada, solicitando que ele reinicie a partida. |
Para organizar melhor o código, decidi implementar cada funcionalidade separadamente. No draw() elas são chamadas após o usuário iniciar o jogo:
if(tela) {
background(29, 212, 216);
fill(255);
textSize(15);
text("APERTE 'ESPAÇO' PARA COMEÇAR", 25, height/2);
stroke(255);
line(20, (height/2)+20, width-30, (height/2)+20);
line(50, (height/2)+35, width-65, (height/2)+35);
}
else {
background(255, 193, 7);
colisaoBola();
ellipse(bolaX, bolaY, raio, raio);
colisaoBarra();
rect(barraX, height-alturaB, larguraB, alturaB);
colisaoSprites();
}
Caso as duas caixas sejam eliminadas e a bola não caia no chão, o usuário vence a partida.
![]() |
| Colisão com a barra e as paredes implementadas. |
A colisão da bola foi implementada nesta função:
void colisaoBola() {
bolaX += velX;
bolaY += velY;
// paredes
if((bolaX > width-(raio/2)) || (bolaX < 0+(raio/2))) {
velX = -velX;
}
if(bolaY < 0+(raio/2)) {
velY = -velY;
}
// barra
if((bolaX + raio/2 >= barraX) && (bolaX - raio/2 <= barraX + larguraB) &&
(bolaY + raio/2 >= height - alturaB) && (bolaY + raio/2 <= height)) {
velY = -velY;
}
// caso caia no chão
if(bolaY > height) {
background(255, 87, 34);
textSize(19);
fill(255);
stroke(255);
text("VOCÊ PERDEU!", width/2 - 70, height/2-25);
line(25, height/2-7, width-28, height/2-7);
text ("APERTE 'R' PARA REINICIAR", 25, height/2+25);
}
}
Ao apertar o botão 'R' todos os valores iniciais são "resetados", ou seja, seus valores atuais são atualizados como iniciais. Assim, foi possível reiniciar o game.
![]() |
Caso o jogador vença, aparecerá uma tela de vitória.
Link do Código: https://drive.google.com/open?id=1S0aP7P3ImJCn0xRmsgp3qoSmpQTyVaGH |
terça-feira, 15 de outubro de 2019
Trabalho MAMI - Parte I
O jogo escolhido para o trabalho foi o Blip, lançado em 1977, da primeira geração de jogos eletromecânicos comercializados pela Tomy. É bastante similar ao Pong da Atari, sendo a maior diferença o fato de ser um jogo de matriz mecânica, ao invés de eletrônica, como o primeiro.
Link do vídeo: https://www.youtube.com/watch?v=iBoe3yM9IKs
Mecânicas e jogabilidade:
O jogo possui dois modos de jogo, individual e de dois jogadores, que pode ser alternado por um switch na tela.
→Bola:
Quando é iniciado, uma bola, que é uma luz de LED, adquire uma velocidade inicial fixa e viaja de um lado da tela para outro.
→Pás:
Os jogadores precisam antecipar onde a bola irá parar e selecionar um dos três slots disponíveis conforme a sua escolha, que são posições predefinidas das "pás" do jogo, com o objetivo de aparar a bola e retornar ao seu adversário.
→Pontuação:
Se um dos jogadores escolher errado a posição da pá, a bola passa e conta pontuação para o adversário. Caso escolha certo, é retornada ao adversário.
→Condições de Vitória:
O jogo continua até que um dos jogadores alcance 10 pontos ou o quando timer parar. Nesse último caso, ganha o jogador que tiver feito a maior pontuação.
→Término do jogo:
Quando o jogo termina, as pontuações, o timer e a posição da bola são reiniciados.
Recriação:
Pelas limitações técnicas da época, Blip é um jogo simples e os movimentos da bola são relativamente fáceis de prever. As técnicas usadas no jogo original para simular colisão da bola e a movimentação limitada das pás o deixa entendiante rapidamente. Dessa forma, a minha versão aproxima o jogo mais do Pong da Atari para torná-lo mais interessante, mas mantendo as características e regras do Blip.
Modelo Natural:
O modelo natural consiste em duas pás, representando os dois jogadores, a bola, que é utilizada para marcar a pontuação, os marcadores de tempo, cronômetro e a tela de game over.
Controles:
Jogador 1:
W: Movimenta a pá para cima
S: Movimenta a pá para baixo
Jogador 2:
↑: Movimenta a pá para cima
↓: Movimenta a pá para baixo
Assim como jogos similares, tais como o Pong, faz-se um paralelo com o tênis de mesa: as pás são as raquetes físicas dos jogadores mas, ao contrário deste, assume-se que a bola sempre irá passar por cima da rede, ou que não exista rede interpondo os dois jogadores. Além disso, no tênis de mesa não há colisão lateral com a bola.
Também é similar aos aero-hóqueis ou air game de fliperama. Neles também há a colisão lateral, mas a área de colisão é estendida às laterais das extremidades, sendo a parte central o "gol".
Modelo Matemático:
Para medidas espaciais
1 unidade = 1 pixel
X(pá direita) = 40
X(pá esquerda) = X-40
Y(ambas pás) = Y/2 = -250
vel (pás) = 5 px/fr
velX (bola) = 8 px/fr
velY (bola) = 8 px/fr
Caso a bola ricocheteie nas paredes ou nas pás:
velX (bola) = -(velX (bola)) (horizontalmente)
velY (bola) = -(velY (bola)) (verticalmente)
Caso um jogador marque um ponto:
ponto(jogador) = ponto(jogador) + 1
Se o jogo acabar (para cada frame):
tempo = tempo + 0
Reinício:
tempo = 0
tempo = tempo + 0,01666...
Modelo Computacional:
Tipos de Funções:
Criação de objetos - As mais simples, são de grande ajuda para desenhar os componentes do jogos na tela e estabelecer seus parâmetros.
desenhaBola(): Cria a bola seguindo os parâmetros de diâmetro e posicionamento.
desenhaPa(): Cria as pás seguindo os parâmetros de largura, altura e posicionamento.
Movimentação - Funções que incrementam ou decrementam os valores iniciais dos objetos que se movem na tela.
movePa(): Acresce ou decresce o valor da velocidade da pá aos seus respectivos valores verticais.
moveBola(): Acresce os valores da velocidades X e Y da bola ao seus respectivos valores de posicionamento.
Colisão - Funções que limitam o espaço de atuação e/ou modificam a velocidade da bola.
limitaPa(): Limita a posição das pás para que elas não saiam da tela.
contatoPa(): Ao entrar em contato com a pá, a variável de velocidade da bola torna-se negativa.
colisao(): Assim como a última, quando alcança a altura máxima da tela, a velocidade Y da bola se torna negativa, o que acontece respectivamente com a velocidade X, se alcançar a largura máxima.
Caso não haja a colisão nas bordas, e o X máximo seja ultrapassado, será contabilizado 1 ponto para o jogador que marcou,
Condição de Vitória - Função que valida as possíveis vitórias.
gameOver(): Encerra o jogo, caso as condições estabelecidas sejam cumpridas. Assim como no Blip, as condições de vitórias são as mesmas. Ganha quando o contador de pontos chegar em 10, ou o de tempo alcançar 60.
HUD - Funções que mostram informações relacionadas ao jogo, tais como: tempo, pontuação, etc.
hud(): Exibe a pontuação dos jogadores e o tempo.
paginaGameOver(): Congela a bola e exibe a tela de vencedor, permitindo o reinício do jogo clicando com o mouse aonde pede. Caso reinicie, reseta os valores de tempo, pontuação e posição da bola.
Controles - Funções que permitem a realização do movimento das pás.
keyPressed(): Quando uma das teclas relacionadas ao movimento é pressionada, muda sua respectiva variável booleana para "true", acionando o movimento.
keyReleased(): Quando uma tecla pressionada é solta, muda sua respectiva variável booleana para "false", encerrando o movimento.
Foi a única forma que eu encontrei de deixar que os jogadores jogassem sem interferir no movimento da pá do outro.
Link do código: https://drive.google.com/open?id=1pR89AZAEx2doztYCVoduVylvoolYcfuQ
Mecânicas e jogabilidade:
O jogo possui dois modos de jogo, individual e de dois jogadores, que pode ser alternado por um switch na tela.
→Bola:
Quando é iniciado, uma bola, que é uma luz de LED, adquire uma velocidade inicial fixa e viaja de um lado da tela para outro.
→Pás:
Os jogadores precisam antecipar onde a bola irá parar e selecionar um dos três slots disponíveis conforme a sua escolha, que são posições predefinidas das "pás" do jogo, com o objetivo de aparar a bola e retornar ao seu adversário.
→Pontuação:
Se um dos jogadores escolher errado a posição da pá, a bola passa e conta pontuação para o adversário. Caso escolha certo, é retornada ao adversário.
→Condições de Vitória:
O jogo continua até que um dos jogadores alcance 10 pontos ou o quando timer parar. Nesse último caso, ganha o jogador que tiver feito a maior pontuação.
→Término do jogo:
Quando o jogo termina, as pontuações, o timer e a posição da bola são reiniciados.
Recriação:
Pelas limitações técnicas da época, Blip é um jogo simples e os movimentos da bola são relativamente fáceis de prever. As técnicas usadas no jogo original para simular colisão da bola e a movimentação limitada das pás o deixa entendiante rapidamente. Dessa forma, a minha versão aproxima o jogo mais do Pong da Atari para torná-lo mais interessante, mas mantendo as características e regras do Blip.
Modelo Natural:
O modelo natural consiste em duas pás, representando os dois jogadores, a bola, que é utilizada para marcar a pontuação, os marcadores de tempo, cronômetro e a tela de game over.
Componentes
HUD
Controles:
Jogador 1:
W: Movimenta a pá para cima
S: Movimenta a pá para baixo
Jogador 2:
↑: Movimenta a pá para cima
↓: Movimenta a pá para baixo
Assim como jogos similares, tais como o Pong, faz-se um paralelo com o tênis de mesa: as pás são as raquetes físicas dos jogadores mas, ao contrário deste, assume-se que a bola sempre irá passar por cima da rede, ou que não exista rede interpondo os dois jogadores. Além disso, no tênis de mesa não há colisão lateral com a bola.

Componentes do Tênis
Também é similar aos aero-hóqueis ou air game de fliperama. Neles também há a colisão lateral, mas a área de colisão é estendida às laterais das extremidades, sendo a parte central o "gol".
Componentes de aero-hóquei
Modelo Matemático:
Para medidas espaciais
1 unidade = 1 pixel
X(pá direita) = 40
X(pá esquerda) = X-40
Y(ambas pás) = Y/2 = -250
vel (pás) = 5 px/fr
velX (bola) = 8 px/fr
velY (bola) = 8 px/fr
Caso a bola ricocheteie nas paredes ou nas pás:
velX (bola) = -(velX (bola)) (horizontalmente)
velY (bola) = -(velY (bola)) (verticalmente)
Caso um jogador marque um ponto:
ponto(jogador) = ponto(jogador) + 1
Se o jogo acabar (para cada frame):
tempo = tempo + 0
Reinício:
tempo = 0
tempo = tempo + 0,01666...
Modelo Computacional:
Tipos de Funções:
Criação de objetos - As mais simples, são de grande ajuda para desenhar os componentes do jogos na tela e estabelecer seus parâmetros.
desenhaBola(): Cria a bola seguindo os parâmetros de diâmetro e posicionamento.
desenhaPa(): Cria as pás seguindo os parâmetros de largura, altura e posicionamento.
Movimentação - Funções que incrementam ou decrementam os valores iniciais dos objetos que se movem na tela.
movePa(): Acresce ou decresce o valor da velocidade da pá aos seus respectivos valores verticais.
moveBola(): Acresce os valores da velocidades X e Y da bola ao seus respectivos valores de posicionamento.
Colisão - Funções que limitam o espaço de atuação e/ou modificam a velocidade da bola.
limitaPa(): Limita a posição das pás para que elas não saiam da tela.
contatoPa(): Ao entrar em contato com a pá, a variável de velocidade da bola torna-se negativa.
colisao(): Assim como a última, quando alcança a altura máxima da tela, a velocidade Y da bola se torna negativa, o que acontece respectivamente com a velocidade X, se alcançar a largura máxima.
Caso não haja a colisão nas bordas, e o X máximo seja ultrapassado, será contabilizado 1 ponto para o jogador que marcou,
Condição de Vitória - Função que valida as possíveis vitórias.
gameOver(): Encerra o jogo, caso as condições estabelecidas sejam cumpridas. Assim como no Blip, as condições de vitórias são as mesmas. Ganha quando o contador de pontos chegar em 10, ou o de tempo alcançar 60.
HUD - Funções que mostram informações relacionadas ao jogo, tais como: tempo, pontuação, etc.
hud(): Exibe a pontuação dos jogadores e o tempo.
paginaGameOver(): Congela a bola e exibe a tela de vencedor, permitindo o reinício do jogo clicando com o mouse aonde pede. Caso reinicie, reseta os valores de tempo, pontuação e posição da bola.
Controles - Funções que permitem a realização do movimento das pás.
keyPressed(): Quando uma das teclas relacionadas ao movimento é pressionada, muda sua respectiva variável booleana para "true", acionando o movimento.
keyReleased(): Quando uma tecla pressionada é solta, muda sua respectiva variável booleana para "false", encerrando o movimento.
Foi a única forma que eu encontrei de deixar que os jogadores jogassem sem interferir no movimento da pá do outro.
Link do código: https://drive.google.com/open?id=1pR89AZAEx2doztYCVoduVylvoolYcfuQ
Atividade 8 - Proporções
A função map() recebe como parâmetros o valor a ser convertido, o menor e o o maior valor da extensão atual, e o menor e o maior valor da extensão que é desejada.
Dessa forma, a função recebe a posição de mouse X como valor a ser convertido e a remapeia, confinando-a dentro da largura do retângulo. O mesmo acontece com o mouse Y e a altura do retângulo.
Vale ressaltar que, nesse caso, dX e dY poderiam ser substituídos por mouseX e mouseY sem alterações, uma vez que essas variáveis do sistema têm função parecida ao dist, sempre calculando a posição atual do mouse em função da sua distância da origem.
Link do código: https://drive.google.com/open?id=1hct0aOplnOxSxtaaWpdxGv_AGJNKjPWt
Dessa forma, a função recebe a posição de mouse X como valor a ser convertido e a remapeia, confinando-a dentro da largura do retângulo. O mesmo acontece com o mouse Y e a altura do retângulo.
Vale ressaltar que, nesse caso, dX e dY poderiam ser substituídos por mouseX e mouseY sem alterações, uma vez que essas variáveis do sistema têm função parecida ao dist, sempre calculando a posição atual do mouse em função da sua distância da origem.
Link do código: https://drive.google.com/open?id=1hct0aOplnOxSxtaaWpdxGv_AGJNKjPWt
Assinar:
Postagens (Atom)
























