Na atividade desenvolvida em sala experimentamos retirar pessoas de um cenário, utilizando média, moda e mediana. Após utilizar a moda surgiu um problema de muitos pixels pretos aparecerem na tela dessa forma:
Isso aconteceu porque a moda pega qual a cor de pixel mais repetida em determinado canto da tela, e em alguns pontos da tela não há repetição de pixels, resultando em preto. Portanto, para resolver esse problema, podemos seguir a lógica de que quando o pixel resultar em preto, é só preencher o pixel com o resultado da mediana, ao invés da moda.
O resultado pode ser visto na imagem de cima desse post e no código linkado.
TAREFA – Crie versões no Photoshop da imagem de einstein.jpg e cinza.jpg com variações de brilho e contraste. Qual impacto ocorreu na média e desvio padrão?
Brilho Diminuido:
Brilho Elevado:
Contraste Alto:
Contraste Baixo:
Foi observado que quanto maior o brilho e o contraste maior a variância de valores na tela e portanto um maior desvio padrão, e vice versa.
O clássico selecionado foi o Space Invaders, e para a minha releitura eu escolhi fazer uma versão 3D, que mantivesse a essência e a identidade visual que o jogo adquiriu ao longo dos anos, mas que modificasse sua forma de apresentação e a movimentação, tanto do player quanto dos inimigos.
Download:
Jogo .exe: https://drive.google.com/open?id=1GA8weHytsGTuQs8m5mf4YsGAt7FioL3h
Projeto da Unity + .exe: https://drive.google.com/file/d/1m4P1zdKX0m95bb9RPENNtvxJ4r_N9fcK/view?usp=sharing
(Códigos em Assets/Scripts)
Instruções:
Para jogar abra o arquivo 3DSpace_Invaders.exe
Começar o Jogo - Clique duas vezes no botão de START para começar o jogo
Movimento - Setas ↑ ↓ ← →
Atirar - Barra de espaço
Sair do Jogo - Clique duas vezes no botão de QUIT para sair do jogo
Avaliar criticamente os aspectos visuais e interativos de um dos exemplos apresentados em www.informationisbeautiful.net
Para essa tarefa, eu escolhi o exemplo “Based on a *True* True Story?”
Eu escolhi esse exemplo pois achei seu conteúdo muito interessante. Sua proposta é selecionar alguns filmes de Hollywood que tem sua história baseada em fatos reais, listando-os um abaixo do outro, e analisar se de fato eles estão de acordo com a veracidade dos fatos ou se tiveram alguma licença poética.
Você pode selecionar um dos filmes para visualizara em mais detalhes cena por cena:
Logo de cara você se depara com o título do filme, a veracidade de sua história contada e o ano em que foi lançado:
A página permite que você varie a precisão da análise, podendo escolher entre “Flexível, afinal são filmes”, “Pode tolerar licença poética” e “Apenas a absoluta verdade”.
Também que você veja parte por parte as cenas dos filmes, que tem indicada sua veracidade por uma escala de “Verdadeiro”, “mais ou menos verdadeiro” sendo azul e azul claro e “mais ou menos falso” e “falso de rosa claro a rosa escuro. Achei uma boa escolha de cores por ser inclusiva para daltônicos.
Você pode clicar em uma dessas tags para visualizar apenas as partes do filme com aquela característica:
Embaixo, há uma comparação lado-a-lado da cena do filme com a cena real em que ela é baseada. A informação é resumida ao essencial, o que facilita uma leitura mais dinâmica.
A interação é simples, direta e limpa, comparada à de outras páginas do site, o que me agradou bastante. Todas as informações são exibidas conforme o que você desejar visualizar, o que evita que a tela fique muito cheia de detalhes. O grid escolhido e a disposição dos elementos também facilita a navegação visual pelo usuário.
Explicar o modelo de Diagrama de Rosa, de Florence Nightingale, destacando o impacto social causado à época de sua criação, e gerar uma aplicação que implemente o mesmo com base em dados simulados
Quem foi Florence Nightingale?
Florence Nightingale nasceu por volta de 12 de maio de 1820 em Florença e foi uma enfermeira britânica que ficou famosa por ser pioneira a cuidar de feridos de guerra, durante a Guerra da Criméia. Contribuiu no campo da Estatística, sendo a primeira mulher a integrar a Sociedade Real de Estatística. Também foi pioneira na utilização de métodos de representação visual de informações, por exemplo o gráfico setorial ou “gráfico de pizza”.
A sua contribuição mais famosa foi durante a Guerra da Crimeia, quando começaram a chegar relatos contando sobre as condições horríveis dos feridos. Florence escreveu um livro, em que criou gráficos coloridos, clamando por medidas sanitárias nos hospitais. O impacto de usar gráficos ilustrando suas descobertas evidenciou a importância da informação, pelo alto poder de comunicabilidade. Isso convenceu as autoridades, que, a partir daí, começaram a aplicar medidas sanitaristas.
Ela apresentou os dados que coletou sobre os soldados feridos com as contagens de mortes por mês. Observou a negligência no tratamento aos soldados britânicos, enfrentando a resistência de autoridades militares. Acabou constatando que o número elevado de mortes de soldados se dava principalmente por infecções hospitalares, e não por feridas de batalha, como muitos imaginavam.
O que é o Diagrama da Rosa?
Sua obras impressa “Notas sobre assuntos que afetam a saúde, eficiência e administração hospitalar do exército britânico. Fundada principalmente na experiência do final da guerra. “ (Tradução Livre) continha um gráfico estatístico colorido intitulado "Diagrama das Causas da Mortalidade no Exército do Leste", que mostrava que a doença epidêmica, responsável por mais mortes britânicas no curso da Guerra da Criméia do que ferimentos em campos de batalha, poderia ser controlado por uma variedade de fatores, incluindo nutrição, ventilação e abrigo. O gráfico, que Nightingale usou como uma maneira de explicar estatísticas complexas de forma simples, clara e persuasiva, ficou conhecido como "Diagrama da Rosa" de Nightingale.
Aplicação
O gráfico foi criado com o auxílio de 3 funções arc(), preenchidos com cores diferentes, recebendo inteiros aleatórios para a geração de valores. Para novos valores foi utilizada a função mouseReleased() que gera um novo gráfico a cada clique.
Explicar, com base na trigonometria, a criação de uma aplicação que move um olho que se encontra sempre voltado para o cursor do mouse
LINK DO CÓDIGO
Trigonometria
A trigonometria é a relação dos ângulos e os lados de um triângulo retângulo, e é fundamental para o desenvolvimento dessa aplicação. O Processing possui algumas funções próprias para realizar cálculos, que tem tudo a ver com os cálculos de geometria e trigonometria, mesmo quando não compreendamos o funcionamento delas à fundo.
A função atan2(), que é utilizada nesse código por exemplo:
"Calcula o ângulo (em radianos) de um ponto especificado para a origem da coordenada, conforme medido a partir do eixo x positivo. Os valores são retornados como um float no intervalo de PI a -PI. A função atan2 () é mais usada para orientar a geometria para a posição do cursor.".
A distância que o olho pode percorrer é limitada calculando-se o cosseno e o seno função atan2 para X e Y.
Código
Para essa aplicação foi preciso usar a função atan2() do Processing, calcular a angulação entre a distância da posição do mouse com o centro da tela (atan2(mouseX - width/2), mouseY - (height/2))).
Usei a função atan2() calcular a angulação entre a distância da posição do mouse com o centro da tela, e usei o seno desse resultado para descobrir a coordenada x do circulo preto, assim como o cosseno para descobrir a coordenada y.
Ademais desenhei os círculos que representam o olho e limitei a distância que o centro do olho pode andar pra não ultrapassar os limites (bordas do olho). Para complementar e de efeito estético eu decidi expandir a tela e adicionar um segundo olho que se move independente, seguindo o mesmo raciocínio só que com outras variáveis.
Também para efeito estético adicionei uma imagem de um narizinho e ellipses que representam canduras nos cantos.
Empregando coordenadas polares, explicar o que foi o “norway spiral UFO” (https://www.youtube.com/watch?v=80__LLZ K4zg) e implementar um modelo simplificado que represente o mesmo.
LINK DO CÓDIGO
“Uma curiosa espiral de luz azul e branca apareceu no céu noturno no norte da Noruega e na Suécia, enlouquecendo uma parte do público e gerando um intenso debate entre astrônomos e cientistas, além de teóricos da conspiração. Centenas de pessoas ligaram para o Instituto Meteorológico Norueguês para perguntar o que era. Tudo a partir de anomalias luzes do norte, para alienígenas e wormhole trans-dimensional foi sugerido. Alguns até ligaram o evento aos experimentos de alta energia que estavam acontecendo naquele momento no Large Hadron Collider, na Suíça. A luz foi vista de todo o norte da Noruega, assim como do norte da Suécia, e teria durado 10 minutos”
Independente do que seja o fenômeno em si, é possível notar que a luz trata-se, simplificadamente, de uma espiral.
A Espiral de Arquimedes é um gráfico específico que pode ser gerado com coordenadas polares.
Para o modelo computacional, comecei inserindo variáveis x e y de valor inicial = 0. Para primeiro desenhar uma espiral estática, criei uma função chamada espiral() que contém um laço de repetição, começando em 0 e terminando em 2299 (determina quão grande a espiral vai ser, escolhi esse valor porque era suficiente para o tamanho da minha tela) e incrementando +1.
Foi criada uma variável t que recebe o valor incrementado no laço em radianos. Daí, surgiu a necessidade de se criarem mais duas funções, cartX e cartY, para efetuarem a conversão de coordenada cartesiana para polar. O que elas fazem é receber como parâmetro um valor para o raio, valor de um ângulo e a posição. Em cartX é feito o cálculo do ângulo * t * raio * cos(posição) e em cartY o mesmo só que ao invés de cosseno, utiliza-se o seno.
De volta à função da espiral() a variável x irá receber o valor calculado em cartX, e a variável y irá receber o valor calculado em cartY. Os parâmetros que escolhi foram raio = 100, ângulo = 0.25 e a posição = variável t.
Tendo feito isto, é desenhada uma elipse de raio 25 dentro do laço de repetição, pegando a posição x*0.25 e y*0.25 (o valor multiplicado é para espaçamento, o que também é arbitrário, mas escolhi 0.25 porque se assemelhava ao norway spiral).
Para rotacionar a espiral foi criada uma variável chamada gira, inicialmente igual a 0, que é decrementada em 0.05. Essa variável foi colocada dentro de um rotate(). Também utilizei o pushMatrix() e o popMatrix() para que a rotação acontecesse somente co as elipses.
De efeito estético, foi adicionado uma imagem para ser o fundo do céu e outra imagem representando uma colina.
Para desenhar o barquinho foram utilizadas as formas básicas retângulo e triângulo. Para poder realizar a oscilação do movimento do barco no mar foi necessário o uso da função Seno em um ângulo que era incrementado em 0.05. Essa variável y foi utilizada posteriormente em um cálculo para a função translate. Para rotacionar o barquinho foi preciso utilizar o cosseno do ângulo pela metade, para que o movimento funcionasse corretamente.
Tanto o translate quanto o rotate só deviam agir em uma parte do código, então foram restringidos pelo pushMatrix e popMatrix.
A onda foi feita com várias elipses em um laço de repetição, e seu movimento foi criado utilizando uma cossenoide.
Tarefa: Criar e explicar, com base na teoria dos conjuntos, um dos efeitos disponíveis em http://goo.gl/KATZjk aplicado entre duas imagens à sua escolha
Link do código
Teoria dos Conjuntos
A teoria dos conjuntos é o ramo da matemática que estuda os conjuntos, coleções de elementos. Podemos considerar as imagens exibidas no monitor como coleções de elementos, que no caso são pixels.
Se temos uma imagem A e uma imagem B, elas formam conjuntos separados.
Para realizar a transição de uma imagem A para uma imagem B, nós precisamos que os pixels existentes em A sejam gradativamente substituídos pelos pixels de B, gerando uma intercessão A ∩ B. Isso faz com que, no momento da transição, A e B tenham elementos em comum (pixels que eram somente do B e agora também fazem parte de A), o que caracteriza uma União “A U B”. Ao fim da transição é como se agora A = B.
O que o código a seguir faz é realizar essa alternância de qual conjunto será substituído pelo outro.
Explicação do Código
O efeito escolhido para essa atividade foi o que aparece em 1:58. Ele consiste em uma transição vertical da esquerda para a direita, com uma barra que atravessa a imagem e ao mesmo tempo “revela” outra por baixo.
Para poder reproduzir o efeito de transição foi criada uma função chamada processaImagem(), que pega as informações RGB dos pixels da imagem que estiver sendo mostrada na tela antes da transição e coloca seus pixels na variável imgNova, que vai ser mostrada na tela a seguir.
Foi criada uma variável booleana podePassar que se torna true toda vez que ocorre 1 clique do mouse. Dentro do draw(), é feita a verificação se ela é true, e a nova imagem é exibida gradualmente enquanto o x percorrido não atingir a largura total da tela.
O mesmo é feito com o y, mas dessa vez usando um for. Enquanto y for menor que a altura total da tela, verifica-se se uma variável chamada valor, que no setup foi declarada como valor = 1, continua com esse mesmo valor; Se sim, a imagem mandada como parâmetro para a função processaImagem() é a imagem 1, caso não, a imagem 2 é processada.
Se x alcançar o valor da largura da tela, podePassar se torna falso, e valor se torna negativo, resetando o x.
Assim, a imgNova alterna entre as duas imagens toda vez que ocorre um clique do mouse. Por último, temos a função primeiraImg(), que faz a mesma coisa da processaImagem() mas é executada apenas uma vez (no setup). Ela foi criada para evitar que, na primeira transição entre imagens, apareça um fundo preto, já que a imgNova é perdida durante a transição.
“Criar e explicar uma aplicação que, empregando variáveis para o controle de valores, realiza o processo abaixo numa imagem à sua escolha:”
LINK DE DOWNLOAD
O primeiro passo foi carregar uma imagem, pois a partir do tamanho da mesma será feito todos os passos seguintes. A imagem que eu escolhi tem como dimensões 250x250px, esse valor é importante pois com ele será possível fazer a scanline necessária para aplicar cada filtro. As demais imagens que vão receber o filtro foram criadas com o createImage e o modo de cor HSB.
No início eu determinei uma float ruido para receber a quantidade de ruído a ser aplicado na imagem. Eu coloquei como 20000 por parecer uma quantidade suficiente.
Foi criada uma função para gerar ruído chamada processaRuido(), pois ele se repete em todas as imagens posteriores. A função recebe como parâmetro a float ruido e realiza um scanline seguindo um for que acaba na quantidade predeterminada. As variáveis x, y determinam a posição que o ruído vai ocupar na imagem, e as cores dos pixels são aleatórias.
A função processaImagem() realiza a scanline da imagem original, aplicando os filtros para todas as outras imagens. A imagem cinza recebe os parâmetros pois o que importa é o brilho da imagem (0,0,b). A vermelha (0,s,b) pois a cor vermelha no modo HSB varia em hue de aproximadamente 0-30. A amarela (60,s,b) pois o amarelo é do 30-60. É possível variar a intensidade modificando esses valores.
“Discutir e implementar a simulação interativa de um equipamento, à sua escolha, empregando uma MEF com três ou mais estados”
Para essa tarefa eu escolhi de equipamento uma Televisão.
Como é uma simulação interativa básica, eu decidi que ela iria executar 3 tarefas. Ligar, desligar e mudar de canal (entre 3 opções).
Foram definidas 5 variáveis, sendo uma para cada estado possível
Inicialmente a TV se encontra desligada e o contador de tempo marca 0. Foram criados 3 booleanos inicialmente falsos para alternar entre os estados mais à frente: ligar, up, down.
No setup são carregadas as imagens para cada um dos estados. Como eu queria me aproximar mais de uma TV real eu procurei por uma biblioteca chamada gifAnimation para poder inserir gifs no Processing e utilizar 1 por canal.
Foram criadas 2 funções. A função trocaCanal() define a imagem carregada e o que será exibido na tela para cada variável de estado. A função MEF() define as condições para as trocas de estado, com base nos booleanos criados. O booleano de tempo só é utilizado para “ligar” a TV; o estado ligado muda para o estado Canal 1 quando tempo >= 200, no restante da execução ele é zerado. Os demais booleanos (up, down) servirão para alternar os canais entre si e mantê-los em na sequência (Canal 1, Canal 2, Canal 3).
No início com a função do Processing mousePressed() o booleano ligar se torna verdadeiro e a TV é ligada, de acordo com o que foi definido na função MEF(). Se a TV estiver em algum dos canais e ligar = true, ela será desligada com o clique do mouse (estadoTV = DESLIGADO e ligar = false.)
Com o keyPressed() você pode apertar as setas para cima e para baixo para e alternar entre os canais. Se pressionar para cima, up = true; se pressionar para baixo, down = true. Na função MEF() é feita uma checagem de qual booleano é true para alternar para um Canal na ordem, e o booleano se torna false de novo.
O resultado é esse embaixo (numa qualidade melhor porque esse gif flopou)
E acho que, de maneira bem geral, isso é tudo. Um pouco complicado de compreender de início, mas espero ter ajudado de alguma forma.
“Desenvolver e explicar uma aplicação que apresenta um mapa isométrico com base em dois tilesets à sua escolha”
LINK DO CÓDIGO
O que diabé mapa isométrico?
Mapas isométricos são mapas que, apesar de serem formados por imagens 2D, dão a impressão de possuir profundidade.
A parte mais difícil dessa atividade foi compreender como funciona o posicionamento das tiles, visto que não é como posicionar elementos em uma matriz comum. Devido ao formato de losango das tiles e do mapa em si, é como se a estrutura da matriz estivesse rotacionada em 45°.
Se eu quiser desenhar algo para a direita da tile ((0,0) para (1,0)), por exemplo, eu teria que aumentar valores tanto no eixo X quanto no eixo Y, pois é como um deslocamento na diagonal
Similarmente, para “descer” na matriz, digamos de (0,0) para (0,1), eu estaria aumentando Y e diminuindo X.
Essa é apenas uma forma de raciocínio, que serve mais para visualizar como as coisas funcionam.
Código
Similarmente ao que foi feito em sala de aula, eu comecei selecionando 2 tipos de tiles de mesmo tamanho, 80x70 pixels, e carregando as imagens.
Eu encontrei as tilesets nesse link
Criei uma função chamada mostraMapa() que cria uma matriz indicando a ordem em que os tiles aparecem
Dentro dessa função existem dois for que fazem o trabalho de percorrer as linhas e colunas da matriz e preenchê-la com os elementos através de um switch. Como descrito pelo comentário na imagem acima, eu precisei medir qual o tamanho da parte “visível” das tiles, para então dividir pela metade.
Eu coloquei os valores do cálculo acima para incrementar nas variáveis x (para largura) e y (para altura), assim toda vez que uma tile for posicionada ao lado da outra elas terão o espaçamento adequado.
Ao carregar a imagem existe outro procedimento a ser feito com relação à posição. Subtraindo o valor da metade da largura visível novamente permite que os tiles fiquem na posição correta dependendo da fileira em que estão. Somando o valor da metade da altura visível ao eixo Y permite que uma nova fileira seja criada
Space Invaders é um jogo de videogame de arcade criado por Tomohiro Nishikado e lançado em 1978. Foi originalmente construído pela Taito Corporation no Japão, e um tempo depois foi licenciado para produção nos Estados Unidos pela Midway Games. Space Invaders foi um dos primeiros jogos de tiro com gráfico bidimensional.
O objetivo é destruir ondas de naves com uma espaçonave humana para ganhar o maior número de pontos possível. Para construir o jogo, Nishikado se inspirou na mídia popular, como Guerra dos Mundos e Star Wars.
Space Invaders teve um grande impacto no mercado de arcades e videogames no geral, e foi um dos primeiros exemplos de sucesso japonês na indústria. Foi altamente popular na época e ainda hoje mantém sua reputação como um dos jogos de arcade mais amados e jogados, e continua sendo readaptado para várias plataformas. Grande parte de seu sucesso se deu pela inovação que proporcionou, sendo um jogo que introduziu o conceito de “vidas” para o jogador, fazendo com que a duração do jogo dependesse de sua habilidade.
Mecânicas originais principais
Movimento do personagem:
O jogador controla uma espécie de arma-laser/canhão que se movimenta apenas na horizontal, na parte inferior da tela ;
Tiro do jogador:
O jogador possui munição infinita, com a qual atira de sua posição em direção aos inimigos. Seu tiro os destrói de forma instantânea ao colidir;
Movimento dos inimigos:
Os inimigos estão organizados em linhas, marchando em direção ao jogador. Eles executam movimentos horizontais e avançam 1 passo sempre que alcançam um limite lateral;
Tiros dos inimigos:
Os aliens inimigos ocasionalmente atiram em direção ao jogador e caso um dos tiros o alcance, ele é derrotado e perde uma vida.
Releitura
Procurando modificar algo no jogo original ainda mantendo sua essência, meu objetivo é construir uma versão 3D do jogo, permitindo ao jogador controlar uma nave (também com uma arma laser) que se movimenta não só na horizontal como também na vertical e diagonal. O objetivo é proporcionar mais ação e dinamismo ao jogo. No entanto, com uma maior liberdade de movimentação viria também uma dificuldade elevada, pois seus inimigos são mais numerosos e agora se organizam não só em filas como em colunas, se movimentando tanto na horizontal quanto na vertical.
1. Modelo Natural
Jogo original: “O jogador controla os movimentos da arma "Laser Base", um canhão laser que se movimenta apenas na horizontal, na parte inferior da tela. Da parte superior marcham em direção ao canhão aliens organizados em linhas. O objetivo do jogador é evitar que os aliens atinjam a parte inferior da tela, para essa tarefa o canhão possui munição infinita para atirar. Os aliens, ocasionalmente, atiram em direção ao jogador, se ele for atingido por algum desses tiros, derrota.”
Releitura: O jogador é o sobrevivente da última linha de defesa espacial contra uma horda de invasores. Ele controla os movimentos da nave, que pode aumentar e diminuir sua altitude, se movimentando também na horizontal e diagonal. À sua frente e em sua direção marcham aliens organizados em filas e colunas. O objetivo do jogador é evitar que seus inimigos passem por ele, usando munição infinita para atirar. Os aliens, ocasionalmente, atiram em direção ao jogador, se ele for detectado em sua frente. O jogador é derrotado se for atingido por um desses tiros.
2. Modelo Matemático
2.1 Movimento do personagem:
Inicialmente temos que a nave está parada. As variáveis a seguir são a velocidade nos eixos X e Y:
directionX = 0;
directionY = 0;
Considerando os eixos X e Y, o movimento obedece ao limite lateral (positivo e negativo) e ao superior e inferior estabelecidos:
limiteX = 4;
limiteYSup = 2;
limiteYInf = 0;
Temos que:
Parado: directionX = 0 e directionY = 0
Movimentação para direita: directionX = 1
Movimentação para esquerda: directionX = -1
Movimentação para cima: directionY = 1
Movimentação para baixo: directionY = -1
São utilizados vetores unitários (de comprimento = 1) para mover a nave. A resultante dos movimentos acima permite que a nave se mova também nas diagonais.
paraMover = Vetor normalizado resultante de directionX e directionY
Esse processo de normalização é explicado no esqueminha abaixo:
De forma generalizada (qualquer que seja o sentido do movimento) para estabelecer a nova posição da nave e evitar que ela passe dos limites temos que fazer uma operação de comparação:
N = posição no eixo X ou Y
limiteN1 = limiteX ou limiteYSup
limiteN2 = -limiteX ou limiteYInf
Se N > limiteN1, N = limiteN1
Se N < limiteN2, N = limiteN2
Para o cálculo final do movimento usei também o tempo em segundos que demorou para completar o frame na tela
Logo, a lógica para qualquer direção é basicamente:
(S = So + v * t)
posição = posição + paraMover * tempo;
2.2 Tiro do jogador:
O tiro do jogador é dividido em duas partes:
Shoot (atirar): É a inicialização do tiro.
Para isso precisamos de duas variáveis:
cooldown = 1 (segundos de intervalo entre tiros)
contador = 0
No início, para o jogador começar atirando, temos que:
contador = cooldown
Depois, a cada frame o cálculo será:
contador = contador + tempo (em seg que demorou para completar o último frame)
Daí é preciso fazer uma operação de comparação:
Se contador >= cooldown,
posição da bala(x,y,z) = posição da nave(x,y,z)
Bala: atualização do movimento do projétil
speed = 1
1 vez por frame temos que:
posição z = posição z + speed * tempo (seg)
2.3 Movimento dos inimigos:
As fileiras de inimigos alternam entre dois tipos de movimento. Nos dois, os inimigos avançam um determinado valor (avanço) no eixo Z ao alcançarem os limites estabelecidos.
Movimento horizontal:
Para os cálculos necessários utilizaremos as seguintes variáveis, cujos valores podem ser modificados de acordo com a necessidade:
speed = 1
limiteX = 4
avanço = 0.5
No início temos que
speed = speed * limiteX
Depois, a cada frame
posição X = posição X + speed * tempo (em seg)
Daí, considerando os limites, basta fazermos uma operação de comparação:
Se a posição X >= limiteX ou posição X <= -limiteX
então a velocidade irá inverter (movimento de volta)
speed = -speed
… e os aliens irão avançar no eixo Z em direção ao jogador
posição Z = posição Z - avanço
Movimento vertical:
De forma semelhante, as variáveis serão:
speed = 1
limiteYSup = 2 (superior)
limiteYInf = 0 (inferior)
avanço = 0.5
No início temos que
speed = speed * (limiteYSup - limiteYInf)/2
Depois, a cada frame
posição y = posição y + speed * tempo (seg)
Operação de comparação:
Se a posição Y >= limiteYSup ou posição Y <= limiteYInf
então a velocidade irá inverter (movimento de volta)
speed = -speed ;
...e os aliens irão avançar no eixo Z em direção ao jogador
posição Z = posição Z - avanço
2.4 Tiros dos inimigos:
Dividido em duas partes:
EnemyBullet: é a atualização do movimento do projétil e funciona exatamente da mesma forma que a Bala do jogador, com a diferença de que a velocidade (speed) é negativa (-5)
para calcular a colisão do protótipo existe um raciocínio específico para uma função da Unity, e para explicar como ela funciona sem deixar brechas muito grandes eu vou invadir um pouco a parte do modelo computacional (me desculpem), mas vamos lá
TiroInimigo: A ideia é que os inimigos somente irão atirar no jogador se ele estiver posicionado à sua frente, estejam eles na frente ou atrás, logo eles não irão atirar neles mesmos. Para isso é utilizada uma função própria da Unity chamada Raycast
De forma bem simplificada, o que ela vai fazer é projetar um raio (infinito positivo) que parte da posição de cada inimigo, e para cada objeto que esse raio atinge ele executa uma operação de comparação:
Se a tag do objeto = tag do player. Se for, os inimigos irão atirar (possoAtirar).
Variáveis
contador = 0
cooldown = 3 (seg)
Da mesma forma que no tiro do jogador:
A cada frame o cálculo será:
contador = contador + tempo (em seg que demorou para completar o último frame)
Daí é preciso fazer uma operação de comparação:
Se contador >= cooldown (e possoAtirar for verdadeiro de acordo com o raycast)
posição da EnemyBullet(x,y,z) = posição do inimigo que atira(x,y,z)
3. Protótipo
Para simular a releitura, no lugar de apenas uma animação eu fiz já o protótipo do jogo, que será desenvolvido na Unity, demonstrando suas mecânicas básicas.
Por fins ilustrativos, vou deixar alguns gifs aqui e o vídeo completo está para download embaixo (me perdoem, eu sou muito ruim jogando)
Algumas demonstrações de movimentos:
Movimento Horizontal do player e Movimentos dos inimigos
Movimento Diagonal do player
Troca de tiros
Dinâmica do jogo
4. Link de download
No link do drive acima estão:
o vídeo (VideoPrototipo.wmv ou VideoPrototipo.mp4)
o protótipo executável (3DSpace_Invaders.exe)
a pasta da Unity zipada com todos os arquivos (Space_Invaders.rar)
Tarefa: Explicar 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 do jogo Pong com dois bastões, controlados respectivamente pelas teclas w e s e pelas setas para cima e para baixo do teclado.
Link de download
Pong
É um jogo clássico, no qual dois bastões, em lados opostos da tela, disputam uma partida rebatendo uma bolinha. O objetivo do jogador 1 ou 2 é impedir que a bolinha bata na parede que está do seu lado, e, caso não consiga defender, seu adversário ganha um ponto. No programa em questão, o jogo tem fim quando um dos lados marca 11 pontos.
keyPressed ou keyPressed()
Apesar de executarem a mesma função há uma diferença em seu modo de funcionamento.
A variável booleana keyPressed é utilizada juntamente com uma condicional if e é executada somente se a tecla escolhida por pressionada. É independente do draw() e se mantém true se e enquanto a tecla está sendo pressionada, e se torna false quando a tecla é solta.
A função keyPressed() funciona como um “evento” dentro do programa, que é executado pelo draw() toda vez que ele roda. Ela é chamada 1 vez toda vez que a tecla é pressionada. Por causa de como os sistemas operacionais lidam com repetições de teclas, manter pressionada uma tecla pode gerar várias chamadas para o keyPressed(). A taxa de repetição é definida pelo sistema operacional e pode ser configurada de maneira diferente em cada computador.
A diferença entre usar um e outro não é sempre perceptível, porém, de acordo com a definição, funções na categoria de “evento” como o keyPressed() alteram o fluxo normal do programa. É possível que haja um certo delay ao utilizar a função, visto que ela depende do draw() e é lida por ele uma vez a cada execução, o que já não é percebido quando se usa a variável. É possível deduzir assim que o uso da variável permita uma maior “fluidez” no código.
Como funciona
A construção é simples, são posicionados retângulos em posições centrais opostas. Para fins de organização, foram diferenciados como “Bastao1″ e “Bastao2″. Foram criadas variáveis para a posição x e y de cada.
Para ambos existem condicionais que os impedem de ultrapassar os limites de altura da tela. (caso a posição seja >= height-100 e < 0)
Foi criada uma função chamada controles(), que contém as condicionais para a movimentação dos bastões. Como são controlados pelo teclado, existiam duas opções disponíveis: a variável booleana do sistema keyPressed e a função keyPressed(). Eu optei por utilizar a variável booleana.
O bastão 1 é controlado pelas setas para cima e para baixo, que ao serem pressionadas adicionam -10 ou +10 à bastaoY1.
O bastão 2 é controlado pelas teclas W e S, que funcionam da mesma maneira mas incrementam bastaoY2.
A bolinha possui velocidade X diferente da velocidade Y para o movimento parecer mais natural. São feitas checagens com as paredes e com os bastões. Isso tem a ver com o tamanho deles. Caso a bolinha encoste e “ultrapasse” o tamanho de algum bastão ou encoste nas paredes a sua velocidade é invertida.
Por fim, apesar de não necessário para a atividade, os pontos são contados por variáveis chamadas contador1 (bastão da direita) e contador2 (bastão da esquerda), que são incrementadas se a bolinha bater em uma das paredes. Para o bastão da direita, o contador1 é somado se a bolinha estiver na primeira metade da tela, e vice versa.
Uma variável booleana chamada “fim” controla quando o jogo acaba. Enquanto ela é falsa todas as funções são executadas no draw(), e ela se torna verdadeira quando um dos bastões marca 11 pontos. Nesse momento é exibida uma mensagem na tela indicando o fim com a pontuação.
Tarefa: 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.
Link de Download
Função dist()
Dada as coordenadas de 2 pontos distintos, calcula a distância entre eles.
Ex: ponto (x1,y1) e ponto (x2,y2) seriam escritos da seguinte forma dist(x1,y1,x2,y2)
Função map()
Serve para “remapear” um número de uma escala para outra, fazendo uma espécie de regra de 3 para calcular o valor inserido proporcionalmente na mesma escala.
Por exemplo, se desejássemos encontrar o equivalente ao ponto (0.5, 0.3) de uma janela de 1x1 em uma tela 1920x1080 faríamos uma regra de três simples.
Utilizando a função map() nós escreveríamos para o ponto X, por exemplo map(0.5, 0, 1, 0, 1920). O primeiro parâmetro é o valor que desejamos converter, o segundo e terceiro são os valores mínimo e máximo inicial, o quarto é o valor mínimo da escala para qual deseja converter e o quinto é o máximo.
O Programa
Com base nessas duas ideias foi estabelecida a lógica necessária para o programa.
O primeiro passo foi criar a tela com as proporções desejadas. Eu escolhi o tamanho 400x300 (4:3 x100). No draw() foi desenhado um retângulo utilizando o rectMode(CENTER) para estabelecer sua origem pelo seu centro. Após posicionar no centro da tela, o tamanho escolhido foi 160x90 (16:9 x10).
Queremos que um elemento da tela siga o mouse, e como estamos tratando de distâncias proporcionais, a função dist() foi utilizada para calcular a distância dX entre o ponto (0,0) e o (mouseX, 0), e a distância dY entre o ponto (0,0) e o (0, mouseY).
A elipse deve seguir o mouse e ter seu movimento restrito ao retângulo, mas o mouse deve poder mover dentro de toda a extensão da janela do Processing.
Para podermos restringir esse movimento da elipse e ainda assim torná-lo equivalente ao mouse na janela, utilizaremos a função map(), que fará uma regra de três.
Essa é a parte mais complicada do exercício, mas um esquema desenhado facilita a compreensão:
Eu medi a posição de cada coordenada do retângulo a partir de seu ponto central e do tamanho da janela. Nós precisamos para a regra de três do ponto superior esquerdo e do ponto inferior direito.
Agora é só a sopinha no mel, meus caros.
Vamos destrinchar a posição (x,y) da Elipse desenhada em xEllipse e yEllipse, e para cada um utilizaremos map()
dX e dY são as distâncias que calculamos lá em cima, e serão os valores de referência na função map(). Assim, em xEllipse:
A mesma lógica se repete para yEllipse e assim estão delimitadas as distâncias que a bola pode seguir. Por último basta usar xEllipse e yEllipse como parâmetros ao desenhar a ellipse e voilà.
Tarefa: discutir os aspectos matemáticos envolvidos na criação de marcas responsivas ou adaptativas, destacando o emprego da programação para a viabilização das mesmas.
O que são Marcas Responsivas?
Antes de prosseguirmos para a tarefa, é necessário esclarecermos primeiro a pergunta acima.
O termo responsivo, no contexto de web design, é sinônimo de algo que é ajustável. Possui esse nome porque responde ao meio que está, e no caso do ambiente digital, o meio tem relação com o dispositivo e seu tamanho de display.
A responsividade é uma técnica utilizada por profissionais do design, que tem como objetivo desenvolver versões de logotipos já existentes para que sejam facilmente adaptados (ajustáveis) a diversos dispositivos — grandes e pequenos — sem sofrer cortes e/ou alterações* que prejudiquem o seu reconhecimento. No caso do webdesign, isso também se aplica às interfaces e ícones de forma geral.
*fonte
E o que a matemática tem a ver com isso?
Veja bem, por mais que tentemos fugir da matemática, ela nunca larga do nosso pé. Para falar a verdade, ela está em simplesmente tudo. (desculpa acabar com a sua ilusão).
No Design, como em qualquer outra coisa, obedecemos à regras, e estabelecemos elas também para nossas criações. Quando desenvolvemos a identidade visual de uma marca, que irá representar uma instituição, um produto ou uma empresa, precisamos ter certeza de que ela será reconhecida sempre por todos.
Para que isso aconteça, não queremos que um determinado design seja modificado ao ser aplicado no cenário A ou B. Logo, junto com cada logotipo criamos um manual para sua utilização.
Nesses manuais além de cores e tipografia, etc encontramos as regras de proporção estabelecidas. Tudo é medido nos mínimos detalhes. São utilizados “módulos” para padronizar o comportamento da marca, independente da escala de tamanho usada. Como no caso do exercício anterior.
Digamos que primeiro se estabelece uma largura, depois todo o resto é calculado com base em um “módulo” que tem uma relação de proporção com a largura. “O módulo é a largura que você deseja dividida por 5″, por exemplo.
Por meio dessas regras é possível preestabelecer também como esse logotipo irá se comportar em espaços ou telas de tamanhos diversos; quanto de informação visual serão mantida ou retirada. No caso do web design se utiliza muito os media queries em CSS. (ex: se estabelece um tamanho mínimo e máximo de uma tela, seguido das proporções que uma imagem irá tomar). A porcentagem também é muito utilizada para obter resultados de forma prática.
Enfim, são necessários cálculos matemáticos para estabelecer essas proporções e regras geométricas durante o desenvolvimento de um logotipo qualquer.
Emprego da programação
Considerando toda a matemática envolvida, são inúmeras as possibilidades de se empregar programação na criação de marcas.
Alguns exemplos:
1. A incorporação algum movimento dinâmico para tipografia
2. Animações com a logo que respeitem as regras de proporção sem que seja necessário calcular em cada quadro;
3. A adição de detalhes visuais ao aumentar-se o tamanho da imagem
Não necessariamente relacionados com a responsividade, temos uma quantidade N de efeitos que podem ser adicionados com programação que ajudam a tornar o design de algo mais chamativo interessante, desde fade-ins e outs até mudanças de cor e forma.
“Considerando a Lei Federal Nº 5.700, apresentar a criação do procedimento mostraBandeiraBrasil(x, y, l), explicando como rectMode e ellipseMode podem simplificar o processo“
Link de download do código
Após breve consulta, temos que estas são as preposições necessárias para desenvolver o código:
Para cálculo das dimensões, tomar-se-á por base a largura desejada, dividindo-se esta em 14 partes iguais.
Cada uma das partes será considerada uma medida ou módulo (M). O comprimento será de vinte módulos (20 M).
A distância dos vértices do losango amarelo ao quadro externo será de um módulo e sete décimos (1,7 M).
O círculo azul no meio do losango amarelo terá o raio de três módulos e meio (3,5 M).
Variáveis
De início, criei variáveis seguindo as regras. Como dito, a base de tudo é a largura desejada, escolhida arbitrariamente. Escolhi colocar L = 300 e todo o restante é baseado no módulo, que é L/14. O valor de L pode ser modificado a qualquer momento sem prejudicar as proporções.
mostraBandeiraBrasil()
Depois de criar as variáveis o restante é simples. Vamos direto ao ponto do desenho da bandeira em si. A função mostraBandeiraBrasil() só pode receber três parâmetros estabelecidos pelo enunciado. Desta forma:
Float x será a coordenada x
Float y será a coordenada y
Float l será a largura da bandeira
A função rectMode() modifica a localização da origem do retângulo, ou seja, as coordenadas que são desenhados, do canto superior esquerdo (CORNER), para um canto e seu oposto (CORNERS) ou para o centro (CENTER.). Por default, os retângulos são desenhados com CORNER.
No caso desse programa, desenhei o retângulo usando rectMode(CENTER), dando como suas coordenadas x e y (dois primeiros parâmetros) a posição do mouse no eixo X e no eixo Y. Dessa forma a posição da bandeira na janela passa a ser controlada pelo cursor do mouse.
A parte mais complexa do código foi criar o losango, pois para desenhá-lo precisamos das coordenadas de todos seus vértices. E estes. segundo a lei, precisam estar dentro do retângulo mantendo uma distância (d) de 1 módulo e sete décimos das arestas do retângulo.
Fiz os cálculos para cada vértice com o auxílio visual de alguns rascunhos desenhados. É preciso considerar as coordenadas de origem do retângulo (x,y), no meu caso as relações são para o retângulo com origem no centro. Além disso, precisamos a largura e o comprimento da bandeira e o valor d.
Refiz os esboços que estavam no meu caderno digitalmente e o resultado é essa imagem:
Depois de colocar esses valores na função quad(x1,y1,x2,y2,x3,y3,x4,y4) o restante é simples. Para a elipse, que por default do processing já tem o ellipseMode(CENTER), basta colocar as mesmas coordenadas (x,y) do retângulo e o valor de raio*2 como os dois últimos parâmetros.
------
Ao fim do exercício concluí que as funções ellipseMode() e rectMode() podem facilitar muito os cálculos em alguns casos, à depender do que é proposto. Por exemplo, caso seja solicitado desenhar uma figura exatamente no centro da tela, não seria necessário calcular nada, apenas inserir as coordenadas da largura e altura divididas por 2.
Para o exercício de desenhar a bandeira em si (como não há essa exigência e a posição está sendo controlada pelo mouse), não percebi tanta diferença entre desenhar o retângulo no modo Corner e no modo Center, considerando que o que muda são apenas as relações de medida.
Blog de MAMI @liviarco-mami - Tumblr Blog | Tumgag