quarta-feira, 7 de abril de 2021

Pygames: Jogo da cobrinha

No post de hoje vamos desenvolver o famoso game da cobrinha usando o Pygames, cujo o nome oficial é Serpente ou Snake e esteve presente desde o final dos anos 90 em celulares e computadores da época. Você pode baixar o exemplo desenvolvido aqui no seguinte link do GDrive: Clique Aqui

Assim como em posts anteriores, diversos comandos e conjunto de códigos já foram mostrados em postagens anteriores e iremos focar nas novidades que são a formação matricial da cobrinha, como ela é gerada e se movimenta, como é gerado o pontinho e por fim como detectar a colisão entre a cobrinha e o pontinho. 

O primeiro passo é entender como a cobrinha é gerada e isso vai nos remeter ao conceito de matriz, onde podemos entender que a cobrinha é uma matriz linha com entradas cartesianas (x, y). Poderia ser uma matriz coluna também, só mudaria a orientação inicial que em vez de ser no sentido horizontal, seria no vertical (para os posteriores movimentos tem como trocar a posição dela). Observe na figura abaixo, como é desenvolvido a partir do conhecimento matemático, a programação para dar origem ao formato da cobrinha:

Agora você deve estar se perguntando, mas como a cobrinha se desloca pela tela? A resposta está no código abaixo:


Temos que imaginar primeiramente a cobrinha como pontos cartesianos do qual o primeiro ponto (a cabeça da cobrinha) tem uma posição e o segundo (vamos pensar nele como um rabo, mas sendo que tem vários atrás dele na mesma situação) tem uma posição anterior que irá ocupar a posição do primeiro ponto, por isso podemos pensar que esse segundo ponto é sempre um -1 em relação ao primeiro ponto que orienta a movimentação e que será visto a seguir com o uso dos direcionais. Resumindo temos uma eterna superposição de posições orientadas pela cabeça e que com o uso do "for" vamos calculando essas posições anteriores (-1) a serem substituidas dentro do range de tamanho da cobrinha.
Agora que sabemos como a cobrinha consegue se deslocar, precisamos entender como controlar elas com as teclas direcionais. Na primeira parte do código abaixo, temos a programação tradicional de controle de teclas dentro do loop "while" e comandados por "if" que nos entrega os estados que a cobrinha deve estar (0,1,2,3). Você deve estar se perguntando porque entregar um estado ao invés de ir direto para a posição cartesiana e a resposta para isso é devido ao fato de estar em uma movimentação constante, os direcionais devem atuar pontualmente sobre o código senão, não teremos a movimentação adequada (faça uns testes para comprovar isso). Logo em seguida, temos como cada tecla atua na movimentação da cobrinha, lembrando que o código "cobra [0]" é referente a primeira posição matricial da cobrinha e é a que dá a direção da mesma. Se analisarmos o "cobra[0]", ele é composto por um par (x,y) da forma (cobra [0][0], cobra [0][1]), onde para haver uma mudança na direção da cobrinha deve-se ser somado ou subtraido valores numéricos ao par x,y correspondentes. Exemplificando, caso a cobrinha precise subir (Up) temos o valor -10 em y, devido ao fato do ponto zero do plano cartesiano no python estar no canto superior esquerdo e, caso queira descer (Down), é só somar +10 em y. Veja na figura abaixo a ilustração disso e o código utilizado:
 

Agora precisamos entender um pouco sobre como é gerado o pontinho a ser capturado. A geração do ponto aleatório é feita por meio da função "random.randint(0,tamanho máximo da tela)" para os pontos (x,y), porém precisamos ter em mente que ser totalmente aleatório pode causar um desencontro entre o ponto e a cobrinha, já que a cobrinha também tem um tamanho igual a 10 de largura. Tendo isso em mente, usamos um pequeno artifício matemático (por meio desse código x//10 * 10, y//10 * 10) para que sempre que é gerado um valor, ele é dividido por dez gerando um valor inteiro (// é a divisão que devolve um número inteiro, evitando números com vírgula) e ao multiplicar por dez novamente temos um número múltiplo de dez sempre. Com isso padronizamos a geração de números inteiros em intervalos regulares de dez, como podemos ver no código abaixo:


Por fim, a última coisa a tratarmos é como é feita a detecção da colisão entre a cobrinha e o pontinho. Tenha em mente que estamos usando uma maneira mais sofisticada e pronta para detectar as colisões do que as apresentadas anteriormente que dependiam de compararção entre valores cartesianos dos pontos. Como estamos trabalhando matricialmente, temos apenas de criar uma comparação entre duas entradas consecutivas c1 e c2 (cobrinha e pontinho) e verificar se a posição zero e a posição um são iguais entre elas o que torna-se uma colisão. Após a colisão detectada, o pontinho é acrescentado a cobrinha, ganha uma nova posição aleatória na tela e soma-se um ao valor do placar, conforme podemos verificar abaixo:


Com isso encerramos o post de hoje, porém existem outros aspectos que podem ser acrescentados tais como, programações que mantenham a cobrinha na tela visível, fim de jogo quando a cobrinha tocar em sí mesma e outras opções de níveis com maior velocidade ou tamanho inicial da cobra maior. Deixe nos comentários suas descobertas e novos códigos utilizados para o seu game da cobrinha e até a próxima!

quinta-feira, 1 de abril de 2021

Pygames: Desenvolvendo um sistema de quest.

Em muitos games estão presentes sistemas de jogo que te conduzem por uma história, na qual você precisa ter contato com um NPC (personagem não jogável) para cumprir a missão dada por ele para ganhar uma recompensa. Ese sistema é denominado de quest (missão) e é muito utilizado em jogos do tipo MMORPG, mas pode ser usados em outros tipos também. E esse é o foco desse post, desenvolver um layout padrão de um sistema de quest e que você pode encontrar o template usado em: Clique Aqui.


Em primeiro lugar, boa parte do código aqui utilizado já foi trabalhado em posts anteriores, o referente a colisão entre objetos: Clique AquiClique Aqui e o referente a criação de balões de fala para um personagem: Clique Aqui. Portanto não será revisado nesse post detalhes referente a essa construções e sim, apenas ao modo de utilização e adaptação para a estrutura de um sistema de quest.

De modo geral, temos exemplificado a situação onde você conduz o seu personagem jogável (Mário) até o cogumelo (NPC) que ativará por meio de cliques do mouse as instruções para cumprir a missão. A missão consiste em o Mário buscar a moeda para o cogumelo, que finaliza a missão com as falas de agradecimento do cogumelo e uma recompensa.

O primeiro ponto a ser observado é o fato de termos três colisões distintas: entre o Mário e o cogumelo (colidiu()), entre o Mário e a moeda (colidiu2()) e por último entre o cogumelo e a moeda (colidiu3()). As colisões são a maneira mais eficazes para inciar um evento em uma sistema de quest (podem ser usadas outras possibilidades) e garantir que não ocorra situações não previstas. 

Na primeira colisão temos a programação responsável pelas falas do cogumelo (NPC) instruíndo o que deve ser feito. Note que as falas só iniciam quando Mário toca o cogumelo e com consequentes cliques do mouse. Caso não esteja em colisão ou não faça os cliques com o mouse nada acontece e isso é devido as condições colocadas no "if  event.type == pygame.MOUSEBUTTONDOWN and colidiu() == True and colidiu3()== False". Ainda dentro desse "if", encontramos o contador de fala relacionado as falas do cogumelo (falageral = 1) e que quando chega ao valor 5, ele reinicia propositalmente (é para o caso do usuário não ter prestado atenção aos detalhes, poder rever os pedidos do NPC).


A segunda colisão é orientada ao encontro entre o Mário e a moeda e que tem como objetivo o Mário carregar a moeda até o cogumelo. Uma forma disso acontecer é que após a colisão entre os dois, os valores de posição x e y (cartesianos) da moeda passem a ser os mesmos do Mário, assim cria-se o efeito de que ele está levando a moeda até o cogumelo [só tome cuidado para não apertar os direcionais muito rápido, pois a moeda escapa do verificador de colisão e não acompanha os valores cartesianos do Mário).


A última colisão é a do encerramento da missão, onde o Mário carrega a moeda até o cogumelo e temos as falas de encerramento do cogumelo quando a moeda encosta no cogumelo (colisão3). Assim como na primeira colisão temos um contador de fala (no caso ativa as falas do "falageral = 2") que visualmente parece não se repetir, mas se analisar o código você irá notar que ele passa a exibir sempre a fala de agradecimento final (isso foi feito para não dar erro no contador por ter saido fora do quantitativo de falas).


A última modificação nesse layout de sistema de quest é relacionado as exibições de tela, que além dos usuais "tela.blit" ordenados para mostrar personagens e o cenário (precisa ser ordenado pois caso você coloque por exemplo o cenário após os personagens, irá cobrir toda a tela com a exibição do cenário e consequentemente apagando a exibição dos personagens e afins), mostra também as falas que foram organizadas com o "falas[contadordefala]" e "falas2[contadordefala2]" para serem exibidas pelo balão de fala do cogumelo. E por fim, a exibição do premio que só é ativada após a última fala do cogumelo (contadordefala2 >= 1) e exibe na tela um objeto que acompanha os valores cartesianos do Mário (devidamente ajustados para parecer que ele está segurando a bolsa com dinheiro).


Com isso finalizamos esse layout de desenvolvimento de um sistema de quest (missão) e você pode inserir ele dentro da construção do seu game. Além disso ainda é possível fazer melhorias ou inserir novos elementos/missões a serem relizadas. Deixe nos comentários como você implementou esse layout no seu projeto e até a próxima!

Como não perder nenhum compromisso: Meu App Agenda

No nosso dia a dia a agenda é um instrumento de grande importância que as pessoas utilizam para fazer anotações de compromissos ou informaçõ...