Releitura de Clássicos - Parte 2
- Ulisses Silva
- 27 de nov. de 2018
- 7 min de leitura
Continuação do trabalho de releitura de um clássico do Atari. Apresentarei o modelo computacional e a implementação, assim como as diferenças do jogo original.
Krull, relembrando do jogo original

O título que escolhi para releitura foi o jogo "Krull" do Atari 2600.
Para uma melhor explanação sobre esse jogo e o impacto dele na época, acessem o link a seguir da postagem da primeira parte desse trabalho. (link da parte1)
O modelo natural da minha releitura não se passa no universo do filme, mas em um mundo de fantasia medieval genérica. Onde dois personagens, um guerreiro e uma maga, precisam defender o castelo onde moram da invasão de um exército inimigo.
Vídeo explicativo
Como parte do trabalho, precisávamos fazer um vídeo explicando o desenvolvimento do modelo computacional, mostrando a implementação do mesmo e uma comparação entre o original e a releitura. Lembrando que todos os sprites, animações, design, ícones, etc. Foram feitos por mim. Somente os sons e as músicas que peguei de sites de licença gratuita, no caso o open game art (link do site).
OBS: Ao final do post tem o link do executável do jogo! Baixem e se divirtam!!! ^^
Como estava restrito ao tempo limite de 3 minutos para o vídeo, muita coisa foi falada apenas por cima. No entanto, gostaria de deixar aqui um registro mais detalhado sobre a produção da minha releitura.
Modelo Computacional e Matemático
Explicarei agora em maiores detalhes o processo de como foi programar esse jogo.
Primeiramente gostaria de dize que usei como base os vídeos tutoriais do Benjamim (link do canal no Youtube). Em específico um curso gratuito que está disponível no canal dele de um jogo de Hack'n Slash 2D.
Apesar de muitas nuances diferentes, e ter me deparado com situações que ele não contemplava nos tutoriais dele, ele foi de imensa ajuda.
Falando agora da programação em si, em uma das aulas desse semestre aprendemos sobre MEF (máquina de estados finitos), ela foi o ponto chave da minha programação, pois os dois principais elementos do meu jogo (inimigos e jogador) utilizam cada um sua própria MEF para determinar seus comportamentos. A ideia de evitar códigos monolíticos também foi fundamental, já que meu código ficou com muitos scripts que precisavam ser chamados repetidas vezes. Abaixo um exemplo de script, um dos principais na verdade, pois é o responsável pela movimentação dos objetos.

Esse script recebe como argumentos dois valores, um para incrementar a posição X e o outro a posição Y do objeto. Nele também eu faço a checagem da colisão com as paredes. De forma que ele só move, se o movimento não fosse colocá-lo em colisão com a parede. Esse código funciona bem no meu jogo pois como ele é pixel art, a colisão é bem precisa.
Outra sacada foi fazer um sprite retangular genérico, apenas com uma cor qualquer de preenchimento, para funcionar como máscara para os inimigos e os jogadores. O que me deixou mais livre na hora de desenhar as animações dos sprites.
Cada inimigo armazena um conjunto de variáveis que são iniciadas aleatoriamente na criação do objeto. Por isso, alguns inimigos se movem mais rápido que outros, e causam dano diferentemente ao castelo quando escapam. No entanto, todos são passíveis de executar dois tipos de ataque, com lança e com espada. Para isso, a cada mudança de estado, eu gerava aleatoriamente qual ataque ele irá fazer, se é o 1 ou o 2.
A I.A. do inimigo foi muito baseada no uso de alarmes, pois eu não queria que eles simplesmente andassem pra frente e atacasse. Eles param, checam se o jogador está dentro do alcance do tipo de ataque que ele irá fazer, se estiver, eles atacam, se não, eles se movimentam em direção ao castelo.
Abaixo segue a ideia do SPAWNER dos meus inimigos. É uma lógica simples, mas que vai aumentando a dificuldade à medida que você vai matando mais e mais inimigos.

Como podem ver, uma variável local é criada, que conta o número de instâncias do objeto Pai dos inimigos. E contanto que exista um objeto jogador em cena e que esse contador de instâncias seja menor que um valor que eu estipulei, ele gera um inimigo em uma posição aleatória dentro de um determinado limite. O x dele é gerado fora da tela, e o y dentro da faixa de movimentação da tela. O valor que estipulei para a geração de inimigo, é a contagem de inimigos mortos pelo jogador dividido por 4. Dessa forma, à cada 4 inimigos que o jogador derrota, o número máximo de inimigos gerados aumenta. Até um limite de 15, pois em meus testes eu vi que com 15 inimigos ao mesmo tempo já ficava muito difícil.
O objeto do jogador ficou muito parecido com o do inimigo, com a diferença que ele pega os comandos de entrada do usuário das setas e dos botões Z e X. As setas para movimentar, Z para atacar e X para usar o dash.
Arte e Design

Gostaria de ressaltar sobre a arte do jogo, que foi toda de minha autoria. Acima está a imagem que usei para a tela inicial. No jogo coloquei a animação de cada personagem dentro de um objeto que muda de sprite e de posição dependendo da seleção e do comando nas setas. (direita o cursor vai para o guerreiro e esquerda vai para a maga)
Para começar o jogo de fato basta apertar ENTER ou SPACE.
Abaixo seguem alguns exemplos de sprite sheets que criei para os personagens. Algumas animações básicas como respirando, andando e levando golpe, foram fáceis de resolver. Apenas 4 frames.

No entanto, as animações de ataque foram bem trabalhosas. E o trabalho foi em dobro no caso dos inimigos, pois o ataque deles fica piscando. Essa ideia tirei do jogo original, é possível ver que a espada dos inimigos no original brilha. Achei uma boa ideia, já que prepara o jogador e chama a atenção dele para o ataque iminente. Abaixo uma imagem do jogo original.

Os inimigos são coloridos, e a espada deles brilham variando de cor.
Notem que meus sprites já fiz com a sombra embaixo do pé deles, o que também deu um trabalho à mais. Pois, eu poderia ter feito em separado, e na programação fazer sombras seguindo o objeto. No entanto, optei pelo mais trabalhoso mesmo para o programa ficar mais otimizado, economizar espaço na memória.
Abaixo seguem os sprites usados para marcar as barras de Life do jogador e Life do castelo.

Barras com transparência para lembrar vidro.
Eu alterei o alpha da parte vítrea das barras, e no programa gerei retângulos coloridos. Que variam do verde ao vermelho (jogador), e do amarelo ao vermelho (castelo). Para isso, usei uma variável porcentagem que multiplica pelo valor que se altera, no caso a componente green dos retângulos.
Diferenças entre o original e a releitura
No original, a primeira tela do jogo é apenas um dos passos para uma grande aventura, na minha releitura, como eu queria que o usuário se envolvesse mais. Acrescentei um estilo de Hack'n Slash, onde você tem que sair matando os inimigos, e adicionei também uma condição de derrota diferenciada. No caso, a energia do castelo, que, à medida que é invadido, vai levando dano. Dessa maneira o jogador tem duas preocupações constantes, sua própria vida e a do castelo.
Outra diferença é na mecânica, onde implementei um outro botão que agiliza a movimentação pelo cenário, no caso do guerreiro coloquei um "Dash" e na maga um "Teleporte".
A maior diferença no entanto, eu diria que se trata da possibilidade de escolha de dois jogadores diferentes. Eu estava com o pé atrás de implementar isso, pois não conseguia pensar numa abstração que contemplasse isso. Por isso, ao longo do semestre, fui programando como se fosse ter apenas um. Mas devido às aulas de programação que me ajudaram nesse sentido mais abstrato, consegui reorganizar tudo, e me aproveitei do uso de vetores para criar essa variação entre os personagens. De forma que cada um é único, por exemplo. A velocidade de movimento do guerreiro é maior que a da maga, para compensar o ataque à distância que ele não possui e ela sim. No entanto, o dash dele cobre uma menor distância em relação ao teleporte dela. As variáveis de dano de ataque mínimo e máximo também são diferentes entre eles, de forma que a maga possui uma variação menor, o que na prática faz com que ela geralmente mate os inimigos com 2 golpes. Enquanto que o guerreiro possui uma variação maior no ataque, fazendo com que na prática, em alguns momentos ele consiga matar os inimigos com 1 golpe só, mas no geral necessita de 2 ou 3.
Existe também uma diferença sutil na programação. No original, os inimigos sustentam a espada por um tempo antes de desferir o golpe, na releitura eu fiz o mesmo. No entanto, no original, se você encostar na espada do inimigo, mesmo que ele ainda não tenha desferido o golpe, você sofre dano e perde vida. Eu considerei isso como uma falha na programação, e deixei o meu de forma que o objeto que checa a colisão do golpe só é criado no momento exato que o inimigo desfere o golpe.
Considerações finais
Bem pessoal, poderia me estender bem mais falando sobre a programação do jogo e o processo criativo do mesmo. Sobretudo, estou muito feliz com o resultado e orgulhoso de ter conseguido terminar a tempo.
Aprendi muito sobre programar para jogos com esse trabalho em específico. E como tivemos mais liberdade de criação, acabei me empolgando bastante. Deixo aqui como um bônus um link para baixar o executável do jogo. Notem a diferença de pontuação que conseguem com cada um dos personagens!
LINK DO JOGO NO DRIVE!!! (clique aqui)
Comandos do jogo:
Movimentação - Setas do teclado;
Ataque - Tecla 'Z';
Dash/Teleport - Tecla 'X';
Confirmar escolha no menu inicial - ENTER / SPACE;
No menu de fim de jogo qualquer tecla reinicia o jogo;
Obrigado para os que me acompanharam até aqui, aos professores e monitores da UFC que me auxiliaram nesse trabalho. E ao meu amigo Gustavo Rocha pelas dicas de programação.

Bom dia!
Boa tarde!!
Boa Noite!!!

Obrigado!!! ^_^
Comments