Qual é a abordagem correta orientada a objetos para o design de classe no desenvolvimento de jogos?

31

Estou no meio do desenvolvimento de um jogo baseado em sprite 2D para o Windows 7 Phone, usando o XNA. O treinamento e os tutoriais disponíveis para ele são bastante úteis, mas o problema que enfrento é que cada um deles aborda seu design de classe de maneira diferente e o código não é particularmente bem-fatorado. Como resultado, tem sido difícil para mim entender bem quais responsabilidades devo dar a uma classe em particular.

Por exemplo, eu poderia ter uma classe de sprite de base BaseSpriteque sabe desenhar, verificar colisões, etc. Eu poderia ter uma AnimatedSpriteclasse que saberia como navegar em sua planilha de sprite, uma ExplodingSpriteclasse e assim por diante. Essa técnica é demonstrada no exemplo de Space Invaders nos materiais da sessão 2 do Windows 7 Phone Jumpstart .

Como alternativa, eu poderia colocar a maior parte da renderização e executar a responsabilidade do jogo em uma GameScreenclasse; essa classe e suas classes derivadas se comportam mais como formulários ou páginas da Web em termos de suas responsabilidades. As classes Sprite são contêineres mais simples e com muito menos lógica.

Essa é a técnica usada no jogo Alien Sprite do Windows 7 Phone Training Kit e em outros exemplos de gerenciadores de estado de jogos.

Qual é a abordagem correta orientada a objetos para o design de classe no desenvolvimento de jogos?

Josh E
fonte

Respostas:

26

Eu uso uma abordagem mais orientada a componentes, onde você teria uma classe Sprite que possui componentes como Visual, Colisão, Animação, Entrada etc. Com essa abordagem, eu não acabo tendo uma hierarquia profunda de classes (o que é bom) .

Para obter algumas informações sobre o Design Orientado a Componentes, consulte aqui .

thbusch
fonte
2
Marcar com +1 o artigo ao qual você vinculou foi fantástico. Eu estava tão focado no design puro de OO que negligenciei completamente o modelo do tipo componente / decorador.
Josh E
1
O padrão de componente não é realmente "menos pura" OO :)
Srekel
2
De fato. OO é frequentemente equiparado a herança. Mas a herança é apenas uma ferramenta que o OO oferece, a composição é outra.
27510 haffax
Só então. Eu deveria ter sido mais preciso na minha redação; o que eu quis dizer é que me concentrei muito no lado da herança do OO, em vez de pensar nos padrões de design do OO / em outros aspectos do OO que poderiam me ajudar a alcançar o que eu queria.
31710 Josh E
Embora uma abordagem baseada em composições seja bastante óbvia e usada com frequência, ainda não vi uma solução para manter o componente de renderização portátil. Qualquer dica seria ótima.
Andreas
11

Nos jogos, o padrão Component é uma solução comum.

maravilhoso
fonte
esse é outro artigo fantástico - vale a pena ler.
Josh E
1
Ótimo, ótimo, ótimo artigo!
21710 Kevin
6

Os Princípios do SOLID se aplicam tanto ao design do código do jogo quanto a qualquer outra profissão - pelo menos até você otimizar, então eu usaria o seu primeiro exemplo como ponto de partida.

Eu iria além, porque o BaseSprite parece ter a tendência de se tornar uma megaclasse. O princípio de responsabilidade única determina que a colisão, a renderização e a navegação devem ser tratadas por componentes, em vez de entradas individuais em uma hierarquia de classes. A classe holding de todos esses componentes deve lidar apenas com empurrar posições mundiais entre eles.

tenpn
fonte
5

Nos últimos projetos, eu me inclinei mais para uma abordagem no estilo MVC.

No começo, não tínhamos certeza se isso funcionaria, mas funcionou perfeitamente.

Modelo

Os objetos de dados. Apenas os dados puros. Sem comportamento, sem renderização.

Gerenciador de dados. Apenas manipulando "listas" de objetos de dados. (Também pode ser aprimorado para oferecer suporte ao pool.)

Visão

Nós os chamamos de renderizadores. Para cada tipo de objeto de dados, há um renderizador. Quando chamado com um gerente, ele renderiza todos os objetos nessa lista.

Controlador

O mesmo que os representantes, mas controla o comportamento.

Exemplo

O ShipManager possui uma lista de navios. O ShipController moverá os navios de acordo com seu estado. O ShipRenderer renderizará os navios de acordo com seu estado.

Por quê

Dessa forma, a visão e a lógica são estritamente separadas. Isso facilita bastante a migração para uma nova plataforma. Otimizar o layout de dados dentro do XxxManager também é muito fácil.

Andreas
fonte
2
Estou votando contra você porque estou cansado de ver mais ou menos nua "Usar MVC" como uma resposta aceitável. Se você está desenvolvendo em qualquer plataforma moderna, já está usando o MVC em vários níveis. Não é uma resposta específica, e não é uma boa resposta, porque na verdade não diz às pessoas como estruturar classes, que é específica de tarefa / domínio. Você acaba tendo muitas pessoas escrevendo "classe Modal ...; vista de classe ...; controlador de classe ..." MVC é um padrão com muito poder explicativo de alto nível quando se fala em código existente. Não é um padrão com muito poder de planejamento.
4
@ Joe Entendo o seu ponto, mas acho que a sua escolha de palavras é desnecessária e rude. Eu acabei de explicar como fazemos isso. Como a opção de arquitetura de nível superior torna obsoleta a opção de design de nível inferior, considero uma resposta válida.
Andreas