Como projetar um mecanismo de jogo em uma linguagem orientada a objetos? [fechadas]

26

Sempre que tento escrever um jogo em qualquer linguagem orientada a objetos, o primeiro problema que sempre enfrento (depois de pensar em que tipo de jogo escrever) é como projetar o mecanismo. Mesmo que eu esteja usando bibliotecas ou estruturas existentes como SDL, ainda me vejo tendo que tomar certas decisões para cada jogo, como usar uma máquina de estado para gerenciar menus, que tipo de classe usar para carregar recursos etc.

O que é um bom design e como ele seria implementado? Quais são algumas compensações que precisam ser feitas e seus prós / contras?

motor extrópico
fonte
12
O que há de errado em seguir o impulso e refatorar a partir daí, em vez de sofrer uma paralisia da análise?
O Pato Comunista
7
@TheCommunistDuck Porque continuar por impulso é a abordagem adotada em todos os meus projetos anteriores - e cada um deles atinge um limite após alguns meses, quando percebo que qualquer novo recurso exige esforço e complexidade monumentais para adicionar. No momento, passo mais tempo reescrevendo meus mecanismos do que escrevendo o jogo em si, por isso espero que, com um pouco de antecedência e planejamento, poupe tempo a longo prazo.
motor extrópico
3
@ chuzzum, bom ponto. Uma coisa que eu recomendaria então é verificar a arquitetura do mecanismo C4, ou seja; terathon.com/c4engine/images/architecture.png Pode ser um monte de nível superior do que você precisa, mas pode lhe dar algumas idéias ;-)
O comunistas Duck
11
i.imgur.com/81zIY.png
O pato comunista
3
Além disso, essa pergunta é meio vaga. Talvez pegue um de seus exemplos e faça disso uma pergunta mais profunda ou duas.
Tétrada

Respostas:

24

Duvido que alguém seja capaz de dizer 'Você precisa fazer isso e aquilo e isso e isso se encaixa no padrão X'.

No entanto, alguns recursos úteis:
Enginuity - uma série de artigos sobre construção de motores em Gamedev.net.
Codificação de jogos concluída - Eu possuo este livro, e ele aborda todos os aspectos da programação de jogos. Ele também possui um mecanismo construído ao longo do livro.
Arquitetura de Game Engine - Este é outro ótimo livro para o design de motores.
Layout do mecanismo C4 - Retirado do meu comentário, mas isso mostra uma maneira de alto nível de encaixar cada parte do mecanismo.

Isso pode ser um pouco demais para o que você precisa, mas você não pode saber muito sobre algo, e tenho certeza de que receberá um bom plano deles.

EDIT: esqueci os artigos Gamedev foram arquivados desde o novo site, corrigido :)

O Pato Comunista
fonte
O link Enginuity foi quebrado, e os artigos no Google pareciam mostrar que eles não estão mais na web. (?) Os livros parecem bons recursos, e eu estou sempre de olho em mais livros de programação;)
extropic-engine
Além disso, no que diz respeito ao seu primeiro comentário, não espero que alguém elabore um plano mestre adequado a todos os jogos. Acabei de notar, ao longo do desenvolvimento de alguns jogos, que padrões comuns tendem a aparecer muito, então me perguntei o que as outras pessoas usavam em seus jogos.
motor extrópico
11
Corrigido o link.
The Duck Comunista
+1 para enginuity. @chuzzum Basta examinar alguns mecanismos de jogo, deixá-los inspirá-lo e obter a arquitetura ideal para si mesmo. Plus: Muitas vezes, é melhor fazer o seu componente de motor de jogo baseado do que hierárquica, consulte cowboyprogramming.com/2007/01/05/evolve-your-heirachy
Dave O.
11
Eu não diria que é o mecanismo que precisa ser agregado, mais a parte da estrutura da entidade.
The Duck Comunista
7

Como exemplo, veja como meu projeto atual roguelike está estruturado (em Java). Ele está usando um mecanismo de gráficos 2D, então muito do código de renderização já foi resolvido para mim. As críticas são bem-vindas.

class Game
Esta classe configura a máquina de estado que gerencia o estado atual do jogo. (em um menu vs. iniciar um novo jogo vs. jogar um jogo salvo)

interface State
Cada classe State contém dois loops: um loop para atualizar a lógica e um loop para renderização. Eles também contêm código para chamar a Gameclasse e solicitar uma alteração em um estado diferente.

class ResourceManager
Um singleton que é inicializado pela Gameclasse que carrega todos os recursos necessários e permite acesso a eles. Não gosto desse design, pois torna difícil carregar / descarregar recursos em diferentes níveis, por exemplo. Eu provavelmente projetaria isso de maneira diferente se estivesse começando de novo.

class Map
Um mapa contém uma matriz de peças e uma lista de todas as criaturas e itens no mapa. É uma aula bem básica.

class Creature
As criaturas contêm informações sobre si mesmas, incluindo cálculos de movimento (exigindo que eles saibam em que mapa estão e que sejam capazes de consultá-las para descobrir obstáculos). Decidir fazer isso ou ter algum tipo de gerente de classe para cuidar de todas as criaturas é algo com o qual luto.

interface AITask
As criaturas podem ter uma lista de tarefas AIT, que são executadas toda vez que o loop lógico da criatura é executado. A AITask tem seu próprio loop lógico que emite comandos para a criatura e uma condição de término que determina se a tarefa foi concluída com êxito ou não.

interface UIElement
Eu implementei minha própria interface para este mecanismo. Cada UIElement possui um loop de renderização e um loop lógico. Eles também têm um loop para processar a entrada do teclado / mouse. Todos os elementos podem ter vários elementos filhos, que são renderizados após os pais, e assumir a entrada do teclado / mouse. Isso permite que você tenha menus com submenus, por exemplo.

motor extrópico
fonte
O que exatamente está errado com isso? Parece perfeitamente bom para mim.
The Duck Comunista
@TheCommunistDuck Isso não aparece nos exemplos que escolhi, mas tenho muitos problemas com esse código. A classe ResourceManager é uma delas, mas também tenho problemas com os estados - acabo com uma enorme proliferação deles e copio muito código. Especialmente em um RPG, onde o jogador tem muitas opções a qualquer momento, você pode acabar com gráficos de estado realmente complexos. Exemplo: lançando um feitiço. Vai de NormalState -> SelectSpellState -> SelectTargetState -> InvalidTargetState (se falhou) -> DoSpellAnimationState -> NormalState. E isso é apenas uma ação.
motor extrópico
11
Não não. NÃO . NÃO. Por favor não. Oh, espere, você disse que não gosta.
Bartek Banachewicz
6

O primeiro ponto importante a destacar é que não há uma resposta 'boa' para essa pergunta.

A coisa mais próxima de uma resposta certa seria algo como: Depende muito do tipo de jogo, plataforma de destino, restrições (tempo) etc.

Dito isto, existem alguns artigos realmente bons por aí que mostrarão como outras pessoas tentaram responder a esse problema (como eu tentei encontrar informações sobre isso no passado).
Como o pato comunista mencionou, o artigo de enginuity no game dev me ajudou a entender algumas partes da arquitetura de jogos.

Meu design atual é um híbrido do Quake3 / Doom3 e um pouco da biblioteca de classes .NET :)

Eu tenho duas bibliotecas (estáticas ou dinâmicas depende de como você deseja criar / entregar) o Frameworke o Library.

A Biblioteca contém todas as classes auxiliares que existem para ajudar na produção de software de jogos, mas não estão limitadas a esse tipo de produto. isto é, implementa uma lista vinculada, otimizada para o código do jogo, mas que pode ser usada por qualquer coisa que precise do serviço de uma lista vinculada.

O Framework é a essência do 'mecanismo', se você quiser chamar assim. Muito disso segue as filosofias de design do Quake3 (apenas de uma maneira mais orientada a objetos). Ele contém a CLI , o gerenciamento de tempo, o código específico do SO e, eventualmente, as camadas de rede etc.

Esses dois são vinculados ao aplicativo real que está sendo produzido. O Gamese você gosta, que contém o código específico do jogo. Da mesma forma, o Quake3 carrega DLLs, dependendo de qual 'mod' estiver sendo reproduzido.

Para lhe dar uma idéia da estrutura, aqui está uma rápida decomposição de pastas e conteúdos para cada lib:


  • Estrutura
    • IO (classes de gerenciamento de arquivos especializadas, classes de impressão de texto (por exemplo, para a CLI) e registro etc.)
    • Rede
      • Cliente (classes que representam o que o Framework considera uma 'pessoa jogando / conectada ao jogo')
      • Servidor (classes para gerenciar a conexão na estrutura e gerenciar os players)
    • Plataforma (teclado / mouse / controladores manipulando classes, rotinas específicas do SO, como getTime ())
    • Sistema (classes de nível muito baixo, como uma classe de erro, para ajudar na impressão de mensagens de erro, classes de tempo e a própria CLI.)
    • Renderizador (auto-explicativo)
    • etc.

  • Biblioteca
    • Coleções (classes que representam coleções de dados, listas / hashtables vinculadas etc.)
    • Matemática (classes auxiliares básicas de matemática como vetores e matrizes)
    • etc.

HTH! Deve dar algumas dicas ...

Adam Naylor
fonte
Link alternativo para a série Enginuity
Musaffa
-3

Coisas a considerar

  • Linguagens orientadas a objetos têm problemas porque geralmente não possuem funções de primeira classe ou nem todos os dados são objetos (como número inteiro ou flutuante em Java). Os padrões de design solucionam esses problemas com vários padrões. Geralmente é mais rápido codificar e mais fácil manter o uso da linguagem que pode ser usada (objetos de primeira classe); por exemplo, Python (que também permite design orientado a objetos), você terá velocidade mais lenta.
  • Cálculo de evento, para AI pelo menos
  • Lógica Hoare, use pré-condições e pós-condições para pelo menos testar seu código
  • Agentes, olhe para as entidades do Quake
  • Bancos de dados relacionais, maneira poderosa de armazenar dados

Bom design

  • fazer diagrama de ER
  • faça correto
  • crie seu banco de dados, objetos ou estruturas de dados a partir dele

Os dados são essenciais para a programação. Se você deseja bons dados, o algoritmo geralmente surge deles (se você não contar alguns algoritmos numéricos, como determinante da computação).

user712092
fonte
-1, já que esta resposta é muito vaga e confusa. Os bancos de dados relacionais não têm absolutamente nada a ver com um mecanismo OO. Entendo que o inglês não é sua primeira língua, mas você poderia explicar o que você quer dizer com seu primeiro parágrafo? Parece contraditório (as linguagens OO têm problemas, mas é mais fácil programar em linguagens com padrões de design ... embora os padrões de design sejam quase sempre estruturas OO).
The Duck comunista
@duck Contraditório? Para obter problemas que não existem em outros idiomas, resolva-os pelo DP, consulte c2.com/cgi/wiki?DesignPatternsInDynamicProgramming .
precisa saber é o seguinte
@ Duck 1) Você pode usar SQL em C ++ 2) Você pode deduzir atributos de objetos de ER (embora não seja uma prática recomendada) 3) Você pode estruturar dados de relações (esta é uma lista porque eu preciso reordenar os elementos à vontade) este é um hash porque eu preciso de pesquisa rápida)
user712092
@ Duck peço desculpas, cometi um erro ao reordenar. Eu não queria afirmar "DP são mais fáceis para XY", mas "idiomas que podem fazer primeira classe são ...". :)
user712092
Sim, pode haver vantagens para linguagens funcionais. No entanto, mesmo imparcialmente, sinto que uma abordagem OO faz sentido lógico a partir de uma perspectiva gamedev. Além disso, não há motivo para você precisar de um banco de dados relacional em qualquer lugar. Claro, eles podem ser úteis. No entanto, ele não se torna um componente necessário em qualquer lugar.
O pato comunista