Caso essa seja a primeira vez que você teve a oportunidade de ler um de nossos conteúdos, considere-se especialmente convidado a nos acompanhar em uma jornada repleta de conteúdos interessantes sobre desenvolvimento de jogos dos mais diferentes estilos, por meio do uso da plataforma de construção de games Unity.
Por meio da elaboração de diferentes projetos práticos de programação, teremos a oportunidade de aprender os diversos conceitos envolvidos na produção de um jogo e, dessa forma, aprender a utilizar a ferramenta Unity para tirar do papel os games que sempre sonhamos em tornar realidade.
No momento, estamos desenvolvendo o jogo Consultório do Dr. Tratanildo, um game ambientado em um consultório médico tridimensional cujo enredo gira em torno de Tratanildo Doencita, renomado doutor do mundo virtual que realiza excêntricos tratamentos de saúde para seus pacientes por meio do uso de miraculosas pílulas coloridas.
Nossa série é para todos, mesmo àqueles que nunca tiveram a chance antes de tentar desenvolver um game ou sistema: a partir do primeiro texto da série, são abordados desde os tópicos mais básicos do processo, como a instalação e configuração da ferramenta em nossos computadores, até os passos que levarão, de fato, a construirmos divertidos jogos digitais, tais como a inserção e posicionamento dos elementos multimídia nas cenas do projeto e a codificação das regras, metas e interações entre elementos de uma aventura.
Venha conosco para que possamos, juntos, seguir nessa trilha rumo a novos conhecimentos!
Os scripts que tudo governam
Agora que já temos a maior parte dos elementos visuais implementados na cena principal, chegou a hora de voltarmos a implementar scripts controladores em nosso projeto, e dessa vez não são “quaisquer” scripts não: colocaremos a mão na massa nos códigos responsáveis pelo controle das fases, pontuações, tempo e desafios do game.
Para iniciarmos essa tão importante construção, vamos abrir o projeto no editor do Unity. No Unity Hub, clique duas vezes sobre o item referente ao projeto Consultório do Dr. Tratanildo. Na interface inicial do editor, na aba Project, abra a pasta Assets, Scenes e, por fim, clique duas vezes no ícone da cena ConsultorioScene. Por enquanto, mantenha o projeto com a visualização da aba Scene em evidência.
Anteriormente, nós já havíamos iniciado a construção de um script que seria responsável por armazenar informações úteis a todas as cenas de nosso game: trata-se do script Geral, que pode ser encontrado via aba Project, abrindo as pastas Assets e, em sequência, Scripts, conforme indicado a seguir:
Clique duas vezes sobre seu ícone para darmos uma olhada em sua composição no Visual Studio:
Note que, por enquanto, temos bem poucas informações armazenadas na estrutura designada para o script Geral. Sabemos, por exemplo, que trata-se de um script estático (static), portanto tendo seu conteúdo observável pelos demais scripts do projeto sem a necessidade de tê-lo atrelado a um GameObject no projeto.
Por exemplo, o valor da variável pública ModoDeJogoCorrente pode ser lido ou alterado por qualquer script que esteja sendo executado na cena principal do game ou na cena de menu (que ainda não criamos).
Continuaremos a utilizar Geral para armazenar valores de variáveis que sejam importantes a mais de uma cena no game, tais como o modo de jogo (já implementado) e outras informações relevantes, como as que envolvem o placar do jogo e o recorde obtido até então.
Substitua o conteúdo presente dentro das chaves de Geral para o código descrito a seguir:
// Modos de jogo: "Menu", "Consultorio", "BuscaMedicamentos" e "Labirinto"
public static string ModoDeJogoCorrente = "Menu";
public static int PlacarCorrente, RecordeAtual;
Por falar em placar do game, vale aproveitar o momento para definir suas regras: o placar do jogo será atualizado com base em uma relação entre importantes variáveis que iremos configurar posteriormente, tais como a quantidade de agentes de doenças presentes no organismo de um paciente em uma determinada fase e o tempo restante ao final da realização do tratamento do enfermo.
Tanto o placar do game (PlacarCorrente) quanto o recorde da sessão de jogo atual (RecordeAtual) serão visíveis e editáveis pelas cenas principal e de menu.
A variável ModoDeJogoCorrente manterá sua característica de informar ao game como um todo qual é o estado atual da aventura por meio da análise de seu valor armazenado, conforme listado a seguir:
- “Menu”: o jogador ainda não iniciou a aventura, pois está com a cena de menu em evidência na tela;
- “Consultorio”: a aventura já começou, mas Doutor Tratanildo ainda está conversando com o paciente no consultório;
- “BuscaMedicamentos”: Doutor Tratanildo está perambulando pelo cenário principal em busca das pílulas de saúde adequadas ao tratamento;
- “Labirinto”: o tratamento com os fármacos começou, Doutor Tratanildo está operando a máquina e o paciente está sofrendo inclinações enquanto repousa sobre a cama do leito.
Salve o script e volte ao editor do Unity. Agora, iremos criar um novo script que tratará especificamente dos elementos e regras pertencentes a cena principal do game; ele será posteriormente atrelado a um GameObject e funcionará como o “cérebro gestor” das fases em nossa aventura.
Controlador das fases
Na aba Project, ainda com a pasta Scripts em evidência, crie um novo script e conceda-lhe o nome “ControllerFase”, sem as aspas, conforme exemplificado pela imagem a seguir:
Clique duas vezes sobre o ícone do script ControllerFase para iniciarmos sua edição no Visual Studio. Como já nos acostumamos, ao criarmos um novo script, o Unity nos oferecerá algumas estruturas prévias já preenchidas, tais como os métodos Start() e Update(). Mantenha-as, pois utilizaremos suas funcionalidades mais adiante.
Dentro de ControllerFase codificaremos diferentes métodos para a realização de ações que envolverão, dentre outros, a gestão do tempo da fase, das interações entre paciente e médico e dos objetivos a serem alcançados pelo jogador. Antes de iniciarmos a construção dos métodos, vamos realizar a declaração de variáveis que serão essenciais para alcançarmos os objetivos que pretendemos para nosso game.
Primeiramente, nas linhas iniciais do script, logo após o trecho em que consta a frase “using UnityEngine;” insira a seguinte linha de código:
using UnityEngine.UI;
Ao acrescentarmos a biblioteca UnityEngine.UI ao script, indicamos que, em determinados trechos de código a serem introduzidos ali, realizaremos modificações em diferentes elementos da interface de usuário, tais como componentes de texto (Text) presentes em objetos subordinados ao Canvas.
Logo após a primeira abertura de chaves do script, vamos iniciar a declaração das variáveis responsáveis por armazenar informações sobre as fases, introduzindo o conteúdo do seguinte trecho de código:
// Estrutura de composição das fases
public int[] TipoPaciente;
public string[] FalaPaciente;
public string[] FalaDoutor;
public float[] TempoMaxTratamento;
public Vector3[] PosicaoMonstrosAzuis;
public Vector3[] PosicaoMonstrosVerdes;
public Vector3[] PosicaoMonstrosRoxos;
public Vector3[] PosicaoMonstrosAmarelos;
public Vector3[] PosicaoMonstrosVermelhos;
public Vector3[] PosicaoObstaculos;
public Vector3[] DimensaoObstaculos;
public Vector2[] PosicaoInicialPilulas;
Aqui vale uma contextualização importante: em nosso game, cada caso clínico (paciente a ser tratado e suas características) é considerado uma fase, e o jogador somente receberá pontos e progredirá no jogo se conseguir tratar as doenças daquele desafio.
Considerando essa importante característica, vamos analisar sobre o que se trata cada uma das variáveis recém-introduzidas no script:
- TipoPaciente: é uma variável de tipo int (número inteiro) cujo valor representará um dos diferentes modelos de pacientes que temos à disposição na cena do game;
- FalaPaciente: uma variável textual (string) que armazenará a fala do paciente que será exibida na tela assim que ele interagir com o médico no consultório;
- FalaDoutor: uma variável textual (string) que armazenará a resposta de Doutor Tratanildo ao paciente após a primeira interação com o enfermo;
- TempoMaxTratamento: uma variável numérica (float) que armazenará a quantidade total de segundos que teremos à disposição para tratar o paciente na referida fase;
- PosicaoMonstrosAzuis, Verdes, Roxos, Amarelos e Vermelhos: variáveis em que serão armazenadas as coordenadas X e Y em que cada agente de doenças deverá aparecer no labirinto que representa o interior dos corpos dos pacientes;
- PosicaoObstaculos: variável em que serão armazenadas as coordenadas X e Y em que cada obstáculo do labirinto (as paredes internas) deverá ser introduzido;
- DimensaoObstaculos: variável que servirá para armazenar as dimensões de largura e comprimento de cada obstáculo introduzido no labirinto durante as fases;
- PosicaoInicialPilulas: variável que armazenará em quais posições as pílulas deverão ser introduzidas dentro da estrutura do labirinto no momento em que o paciente recebê-las para o tratamento.
Vetores de variáveis
Talvez você tenha notado que, embora a explicação sobre os conceitos envolvidos na criação de cada variável esteja bem clara, ainda falta encaixar uma peça para o pleno entendimento dessa “sopa de letrinhas” que inserimos em nosso script: por que todas as variáveis descritas foram codificadas em formato de vetores, utilizando a notação “[]” logo após a declaração de seus tipos?
Embora nosso script servirá para controlar os aspectos concretos da fase vigente no momento, também aproveitaremos para guardar em suas estruturas as informações sobre todas as fases do game, pois o mesmo script também controlará a passagem de uma fase a outra da aventura.
Ao declararmos “public int[] TipoPaciente”, por exemplo, poderemos informar ao game qual será o tipo de paciente referente à primeira fase (TipoPaciente[0]), à segunda fase (TipoPaciente[1]), e assim sucessivamente.
Outro ponto de atenção que você pode ter notado em relação às variáveis declaradas: se precisamos apenas de dois valores (horizontal e vertical) para indicar onde cada agente de doenças irá aparecer no labirinto, por que estamos utilizando vetores de variáveis de tipo Vector3 em vez de Vector2, como fizemos com PosicaoInicialPilulas?
Nesse caso, faremos diferente da abordagem anterior, pois aproveitaremos o “campo extra” de Vector3 (Z) para armazenar a qual fase se refere àquelas coordenadas. Vamos a um exemplo prático:
Por meio da análise do valor Z de cada variável do tipo Vector3 de PosicaoMonstrosAzuis, Verdes e Roxos, sabemos que, na primeira fase (Z = 0), teríamos três agentes de doenças azuis presentes no labirinto, dois agentes verdes e quatro agentes roxos, todos representados pela cor laranja na tabela de exemplo.
Seguindo a mesma linha de raciocínio, na segunda fase (Z = 1) teríamos dois monstros azuis, dois verdes e um roxo em cena. Por fim, na terceira fase (Z = 2) teríamos apenas dois agentes de doenças azuis e um roxo no labirinto.
A mesma lógica foi adotada para os vetores PosicaoObstaculos e DimensaoObstaculos, que também são compostos por variáveis de tipo Vector3, embora precisem armazenar apenas dois valores úteis (horizontal e vertical).
Curiosamente, para PosicaoInicialPilulas não precisamos utilizar essa abordagem alternativa, pois teremos apenas um ponto de entrada das pílulas por fase. Nesse caso, trata-se de um vetor de variáveis do tipo Vector2 cujo índice representa a fase em questão.
Salve o script e feche o Visual Studio. Não se esqueça de salvar a cena (menu File, opção Save) e o projeto (menu File, opção Save Project) antes de fechar o editor.
Próximos passos
Iniciamos uma etapa importante para o desenvolvimento de nosso game, que consistiu na definição das variáveis iniciais dos scripts controladores da aventura em geral e das fases de cada desafio.
É importante analisar que, para cada decisão criativa que tomamos, determinados elementos de codificação podem nos auxiliar a controlar melhor o andamento das etapas do game, como foi o caso da abordagem “alternativa” que utilizamos para controlar o posicionamento dos agentes de doenças nas fases.
Não há uma só forma certa para se definir esses fluxos de interação entre elementos, em seus próximos games, sempre experimente alternativas que sejam interessantes para seu raciocínio lógico.
Em nossos próximos encontros daremos sequência ao processo de codificação das variáveis e métodos presentes nos scripts controladores de nosso projeto.
Nosso próximo encontro será no dia 16 de março. Até mais! Fique sempre ligado nas novidades do GameBlast!
Revisão: Davi Sousa