Red Alert 2 (Westwood Studios) e Age of Empires 2 (Microsoft) foram dois jogos que definiram a era da computação apenas para se acostumar com a GUI (meados/final dos anos 90).

Originalmente projetado para DOS, o Red Alert foi construído pela Westwood Studios – pioneira em RTS através de títulos como Dune. O jogo foi um avanço devido à sua natureza em tempo real.

Acrescente a isso um enredo matador, gráficos incríveis e mecânica de jogo quase mítica e você tem um vencedor. Como desenvolvedor de software, é fácil ficar maravilhado com jogos como esse… mas outra é saber como eles funcionam. Este tutorial é uma breve introdução ao que eu sei sobre isso.

OOP (Programação Orientada a Objetos)

A coisa mais importante que você precisa apreciar em qualquer jogo é que eles são programados usando princípios OOP. OOP significa programação orientada a objetos e basicamente o oposto da programação baseada em fluxo:

  • Programas baseados em fluxo trabalham com o fluxo de um aplicativo. Eles se concentrarão na entrada do usuário e gerenciarão seu sistema com base em formulários – normalmente atualizando a interface do usuário cada vez que uma entrada é fornecida.
  • Programas orientados a objetos funcionam carregando um aplicativo base e usando-o para carregar uma série de variáveis ​​(objetos). Essas variáveis ​​são mantidas na memória e podem ser interagidas na tela em tempo real.

O núcleo da OOP é a capacidade de “invocar” classes. As classes são um tipo de variável que permite armazenar “atributos” e usar esses atributos nos métodos “público” (classe) e “privado” (instância).A maneira como quase todos os jogos funcionam é invocar vários objetos de dados na memória, preenchê-los com os atributos apropriados (pontos de vida, etc.) .

Dados + Renderizador

Além de uma arquitetura OOP central, os jogos RTS funcionam com dois elementos – um back-end de dados e um front-end “renderer”. Entender como eles funcionam juntos é o cerne para saber se você entenderá como fazer um jogo RTS funcionar de uma perspectiva programática.

Imagine um RTS como um aplicativo simples. Ignore os gráficos e ilustrações etc – concentre-se em como você faria os objetos se moverem na tela.

Funciona assim – o aplicativo é carregado. Isso lhe dá a capacidade de gerenciar suas credenciais (carregar jogos anteriores, alterar seus detalhes etc). O trabalho do aplicativo (em um RTS) é então criar novos “jogos”. Esses jogos existem entre dois ou mais jogadores e funcionam como um tabuleiro de xadrez gigante no qual você pode adicionar novos edifícios, unidades etc.

Cada “jogo” carrega dois conjuntos de dados (seus dados e os do outro jogador). O trabalho do jogo é ajudá-lo a manipular esses dados para derrotar seu inimigo.

Dados (Edifícios / Unidades / etc)

Quando um novo “jogo” é carregado, os dados para você e seus inimigos são carregados na memória. Por exemplo, você pode ter um conjunto de dados que se parece com isso:

  • Jogador #1
    – Edifícios
    – 12
    – 34
    – 81
    – 19
    – Unidades
    – 109
    – 109
    – 109
    – 109
  • Jogador #2
    – Edifícios
    – 12
    – 34
    – Unidades
    – 10
    – 12
    – 24

Cada número acima corresponde a um ID para um objeto de dados. Em bancos de dados relacionais, o ID atuará como uma chave estrangeira.

A maneira como você gerencia esses objetos é ter um armazenamento de dados central (por exemplo, um banco de dados relacional) que armazena os edifícios como objetos específicos por conta própria.

Dessa forma, ao criar um novo edifício, o que você está fazendo é criar uma nova referência no banco de dados. Para Rails, você teria a seguinte configuração:

  • jogadores_mesa
  • factions_table (tem_muitos edifícios, tem_muitas unidades através de edifícios)
  • objects_table (isso será superclassificado como edifícios e unidades)
  • games_table (atua como uma tabela de junção para jogadores) (belongs_to:player_1, belongs_to:player_2)
  • actions_table (isso registra as ações do jogo “o jogador 1 começou a construir x”)

A forma como você configuraria o jogo é a seguinte:

  • O objetivo do aplicativo é criar jogadores
  • Uma vez que o jogador tenha “logado” (com serial ou e-mail), ele poderá criar um “jogo”
  • O jogo permitirá que cada jogador “construa” edifícios e construa unidades. As unidades estão disponíveis através de edifícios (você precisa construir unidades para disponibilizar unidades)
  • Cada edifício/unidade está disponível através de uma facção.
  • Você precisa de algum tipo de árvore tecnológica para permitir a produção específica de unidades / edifícios para determinados investimentos em pesquisa

A maneira como isso funcionaria é carregar um conjunto de dados “em branco” quando o jogo for carregado.A partir daqui, o usuário é capaz de construir os vários edifícios/unidades de nível inferior com os recursos que conseguir reunir. Cada vez que o usuário “cria” um novo edifício, ele está criando um novo objeto de dados que adiciona à sua matriz de edifícios/unidades.

Por favor, aprecie que este conjunto de dados não tem absolutamente nenhuma influência sobre a aparência do jogo.

Parte do que torna os jogos RTS tão atraentes é a ponte perfeita entre dados e renderizador. Imagine os dados como uma lista pura de números, etc. Não há NADA visual nisso.

Na verdade, se você executasse uma visão de “console” do jogo, basicamente veria dois conjuntos de dados, constantemente tendo seus atributos (pontos de vida, posição, etc.) alterados pelo mecanismo do jogo.

Renderizador

É aqui que a mágica acontece e, claro, é o aspecto mais complicado do jogo em si. Eu não tenho nem de longe o nível de experiência com isso, como tenho com os dados puros.

O renderizador é normalmente o que afasta a maioria dos possíveis desenvolvedores.

A forma como funciona é muito simples.

Em primeiro lugar, quando um novo “jogo” é carregado, ele cria um “tabuleiro de xadrez” no qual seus objetos de dados são colocados. Este tabuleiro de xadrez é obviamente o mapa.

O mapa possui restrições (dimensões) que dão ao aplicativo a capacidade de “desenhar” uma grade. Esta grade permite que você use uma série de coordenadas para “posicionar” novos edifícios (objetos).

Enquanto o conjunto de dados não se importa com as posições, o renderizador se importa. Isso significa que se você quiser construir um novo prédio em um local já ocupado por outro, não poderá.

A maneira como você lidaria com isso é enviar as coordenadas em uma nova solicitação de compilação para o servidor. As coordenadas permitirão que o servidor gerencie se o usuário é capaz de construir um novo prédio. Se a resposta for positiva, o motor mostrará a construção do edifício. Caso contrário, não permitirá que o edifício seja construído.

O maior fator com o renderizador está no “AI”.

Esta é a verdadeira magia do jogo. Quando você move uma unidade da posição A para a posição B, como ela interage com outros elementos do jogo, por exemplo.

Linguagens de Programação / Arquitetura

Como você projeta um RTS depende inteiramente do meio em que ele será entregue. Antigamente, você só precisava criar um aplicativo de desktop.

Hoje, você tem a web, mobile e desktop para considerar. Como tal, o cenário geral dos jogos mudou para ser uma experiência mais inclusiva.

Mais importante, vimos o movimento da mecânica do jogo para o servidor. Isso significa que, se você jogar um jogo no navegador, no desktop ou no celular, tudo o que você está fazendo é enviar solicitações ao servidor e ele responderá com atualizações para o renderizador.

Nenhuma das físicas, dados do jogo ou mecânica de construção são mais mantidos no aplicativo do lado do cliente.

Atualmente, não há recursos sobre como desenvolver especificamente um jogo RTS. Se você quiser juntar suas próprias ideias, você fará bem em dar uma olhada no livro Game AI Pro 3 e também um recurso MUITO bom “How to RTS” no GitHub.

 

Deixe um comentário

O seu endereço de e-mail não será publicado.